Host.cpp revision 296417
1218885Sdim//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10276479Sdim// This file implements the operating system Host concept. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14249423Sdim#include "llvm/Support/Host.h" 15239462Sdim#include "llvm/ADT/SmallVector.h" 16239462Sdim#include "llvm/ADT/StringRef.h" 17239462Sdim#include "llvm/ADT/StringSwitch.h" 18249423Sdim#include "llvm/ADT/Triple.h" 19249423Sdim#include "llvm/Config/config.h" 20239462Sdim#include "llvm/Support/Debug.h" 21280031Sdim#include "llvm/Support/FileSystem.h" 22239462Sdim#include "llvm/Support/raw_ostream.h" 23218885Sdim#include <string.h> 24218885Sdim 25218885Sdim// Include the platform-specific parts of this class. 26218885Sdim#ifdef LLVM_ON_UNIX 27218885Sdim#include "Unix/Host.inc" 28218885Sdim#endif 29218885Sdim#ifdef LLVM_ON_WIN32 30218885Sdim#include "Windows/Host.inc" 31218885Sdim#endif 32218885Sdim#ifdef _MSC_VER 33218885Sdim#include <intrin.h> 34218885Sdim#endif 35239462Sdim#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__)) 36239462Sdim#include <mach/mach.h> 37239462Sdim#include <mach/mach_host.h> 38239462Sdim#include <mach/host_info.h> 39239462Sdim#include <mach/machine.h> 40239462Sdim#endif 41218885Sdim 42276479Sdim#define DEBUG_TYPE "host-detection" 43276479Sdim 44218885Sdim//===----------------------------------------------------------------------===// 45218885Sdim// 46218885Sdim// Implementations of the CPU detection routines 47218885Sdim// 48218885Sdim//===----------------------------------------------------------------------===// 49218885Sdim 50218885Sdimusing namespace llvm; 51218885Sdim 52280031Sdim#if defined(__linux__) 53280031Sdimstatic ssize_t LLVM_ATTRIBUTE_UNUSED readCpuInfo(void *Buf, size_t Size) { 54280031Sdim // Note: We cannot mmap /proc/cpuinfo here and then process the resulting 55280031Sdim // memory buffer because the 'file' has 0 size (it can be read from only 56280031Sdim // as a stream). 57280031Sdim 58280031Sdim int FD; 59280031Sdim std::error_code EC = sys::fs::openFileForRead("/proc/cpuinfo", FD); 60280031Sdim if (EC) { 61280031Sdim DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << EC.message() << "\n"); 62280031Sdim return -1; 63280031Sdim } 64280031Sdim int Ret = read(FD, Buf, Size); 65280031Sdim int CloseStatus = close(FD); 66280031Sdim if (CloseStatus) 67280031Sdim return -1; 68280031Sdim return Ret; 69280031Sdim} 70280031Sdim#endif 71280031Sdim 72218885Sdim#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\ 73218885Sdim || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 74218885Sdim 75218885Sdim/// GetX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in the 76218885Sdim/// specified arguments. If we can't run cpuid on the host, return true. 77261991Sdimstatic bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, 78261991Sdim unsigned *rECX, unsigned *rEDX) { 79261991Sdim#if defined(__GNUC__) || defined(__clang__) 80261991Sdim #if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 81261991Sdim // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. 82261991Sdim asm ("movq\t%%rbx, %%rsi\n\t" 83261991Sdim "cpuid\n\t" 84261991Sdim "xchgq\t%%rbx, %%rsi\n\t" 85261991Sdim : "=a" (*rEAX), 86261991Sdim "=S" (*rEBX), 87261991Sdim "=c" (*rECX), 88261991Sdim "=d" (*rEDX) 89261991Sdim : "a" (value)); 90261991Sdim return false; 91261991Sdim #elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) 92261991Sdim asm ("movl\t%%ebx, %%esi\n\t" 93261991Sdim "cpuid\n\t" 94261991Sdim "xchgl\t%%ebx, %%esi\n\t" 95261991Sdim : "=a" (*rEAX), 96261991Sdim "=S" (*rEBX), 97261991Sdim "=c" (*rECX), 98261991Sdim "=d" (*rEDX) 99261991Sdim : "a" (value)); 100261991Sdim return false; 101261991Sdim// pedantic #else returns to appease -Wunreachable-code (so we don't generate 102261991Sdim// postprocessed code that looks like "return true; return false;") 103261991Sdim #else 104261991Sdim return true; 105261991Sdim #endif 106261991Sdim#elif defined(_MSC_VER) 107261991Sdim // The MSVC intrinsic is portable across x86 and x64. 108261991Sdim int registers[4]; 109261991Sdim __cpuid(registers, value); 110261991Sdim *rEAX = registers[0]; 111261991Sdim *rEBX = registers[1]; 112261991Sdim *rECX = registers[2]; 113261991Sdim *rEDX = registers[3]; 114261991Sdim return false; 115261991Sdim#else 116261991Sdim return true; 117261991Sdim#endif 118261991Sdim} 119261991Sdim 120261991Sdim/// GetX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return the 121261991Sdim/// 4 values in the specified arguments. If we can't run cpuid on the host, 122261991Sdim/// return true. 123276479Sdimstatic bool GetX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, 124276479Sdim unsigned *rEAX, unsigned *rEBX, unsigned *rECX, 125276479Sdim unsigned *rEDX) { 126218885Sdim#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 127218885Sdim #if defined(__GNUC__) 128218885Sdim // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually. 129218885Sdim asm ("movq\t%%rbx, %%rsi\n\t" 130218885Sdim "cpuid\n\t" 131218885Sdim "xchgq\t%%rbx, %%rsi\n\t" 132218885Sdim : "=a" (*rEAX), 133218885Sdim "=S" (*rEBX), 134218885Sdim "=c" (*rECX), 135218885Sdim "=d" (*rEDX) 136261991Sdim : "a" (value), 137261991Sdim "c" (subleaf)); 138218885Sdim return false; 139218885Sdim #elif defined(_MSC_VER) 140288943Sdim int registers[4]; 141288943Sdim __cpuidex(registers, value, subleaf); 142288943Sdim *rEAX = registers[0]; 143288943Sdim *rEBX = registers[1]; 144288943Sdim *rECX = registers[2]; 145288943Sdim *rEDX = registers[3]; 146288943Sdim return false; 147234353Sdim #else 148234353Sdim return true; 149218885Sdim #endif 150218885Sdim#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86) 151218885Sdim #if defined(__GNUC__) 152218885Sdim asm ("movl\t%%ebx, %%esi\n\t" 153218885Sdim "cpuid\n\t" 154218885Sdim "xchgl\t%%ebx, %%esi\n\t" 155218885Sdim : "=a" (*rEAX), 156218885Sdim "=S" (*rEBX), 157218885Sdim "=c" (*rECX), 158218885Sdim "=d" (*rEDX) 159261991Sdim : "a" (value), 160261991Sdim "c" (subleaf)); 161218885Sdim return false; 162218885Sdim #elif defined(_MSC_VER) 163218885Sdim __asm { 164218885Sdim mov eax,value 165261991Sdim mov ecx,subleaf 166218885Sdim cpuid 167218885Sdim mov esi,rEAX 168218885Sdim mov dword ptr [esi],eax 169218885Sdim mov esi,rEBX 170218885Sdim mov dword ptr [esi],ebx 171218885Sdim mov esi,rECX 172218885Sdim mov dword ptr [esi],ecx 173218885Sdim mov esi,rEDX 174218885Sdim mov dword ptr [esi],edx 175218885Sdim } 176218885Sdim return false; 177234353Sdim #else 178234353Sdim return true; 179218885Sdim #endif 180234353Sdim#else 181234353Sdim return true; 182218885Sdim#endif 183218885Sdim} 184218885Sdim 185288943Sdimstatic bool GetX86XCR0(unsigned *rEAX, unsigned *rEDX) { 186251662Sdim#if defined(__GNUC__) 187251662Sdim // Check xgetbv; this uses a .byte sequence instead of the instruction 188251662Sdim // directly because older assemblers do not include support for xgetbv and 189251662Sdim // there is no easy way to conditionally compile based on the assembler used. 190288943Sdim __asm__ (".byte 0x0f, 0x01, 0xd0" : "=a" (*rEAX), "=d" (*rEDX) : "c" (0)); 191288943Sdim return false; 192251662Sdim#elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) 193288943Sdim unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); 194288943Sdim *rEAX = Result; 195288943Sdim *rEDX = Result >> 32; 196288943Sdim return false; 197251662Sdim#else 198288943Sdim return true; 199251662Sdim#endif 200249423Sdim} 201249423Sdim 202218885Sdimstatic void DetectX86FamilyModel(unsigned EAX, unsigned &Family, 203218885Sdim unsigned &Model) { 204218885Sdim Family = (EAX >> 8) & 0xf; // Bits 8 - 11 205218885Sdim Model = (EAX >> 4) & 0xf; // Bits 4 - 7 206218885Sdim if (Family == 6 || Family == 0xf) { 207218885Sdim if (Family == 0xf) 208218885Sdim // Examine extended family ID if family ID is F. 209218885Sdim Family += (EAX >> 20) & 0xff; // Bits 20 - 27 210218885Sdim // Examine extended model ID if family ID is 6 or F. 211218885Sdim Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 212218885Sdim } 213218885Sdim} 214218885Sdim 215276479SdimStringRef sys::getHostCPUName() { 216218885Sdim unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 217218885Sdim if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX)) 218218885Sdim return "generic"; 219218885Sdim unsigned Family = 0; 220218885Sdim unsigned Model = 0; 221218885Sdim DetectX86FamilyModel(EAX, Family, Model); 222218885Sdim 223261991Sdim union { 224261991Sdim unsigned u[3]; 225261991Sdim char c[12]; 226261991Sdim } text; 227261991Sdim 228288943Sdim unsigned MaxLeaf; 229288943Sdim GetX86CpuIDAndInfo(0, &MaxLeaf, text.u+0, text.u+2, text.u+1); 230261991Sdim 231288943Sdim bool HasMMX = (EDX >> 23) & 1; 232288943Sdim bool HasSSE = (EDX >> 25) & 1; 233288943Sdim bool HasSSE2 = (EDX >> 26) & 1; 234288943Sdim bool HasSSE3 = (ECX >> 0) & 1; 235288943Sdim bool HasSSSE3 = (ECX >> 9) & 1; 236288943Sdim bool HasSSE41 = (ECX >> 19) & 1; 237288943Sdim bool HasSSE42 = (ECX >> 20) & 1; 238288943Sdim bool HasMOVBE = (ECX >> 22) & 1; 239288943Sdim // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV 240249423Sdim // indicates that the AVX registers will be saved and restored on context 241249423Sdim // switch, then we have full AVX support. 242249423Sdim const unsigned AVXBits = (1 << 27) | (1 << 28); 243288943Sdim bool HasAVX = ((ECX & AVXBits) == AVXBits) && !GetX86XCR0(&EAX, &EDX) && 244288943Sdim ((EAX & 0x6) == 0x6); 245288943Sdim bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0); 246288943Sdim bool HasLeaf7 = MaxLeaf >= 0x7 && 247288943Sdim !GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); 248288943Sdim bool HasADX = HasLeaf7 && ((EBX >> 19) & 1); 249288943Sdim bool HasAVX2 = HasAVX && HasLeaf7 && (EBX & 0x20); 250288943Sdim bool HasAVX512 = HasLeaf7 && HasAVX512Save && ((EBX >> 16) & 1); 251288943Sdim 252218885Sdim GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 253218885Sdim bool Em64T = (EDX >> 29) & 0x1; 254276479Sdim bool HasTBM = (ECX >> 21) & 0x1; 255218885Sdim 256218885Sdim if (memcmp(text.c, "GenuineIntel", 12) == 0) { 257218885Sdim switch (Family) { 258218885Sdim case 3: 259218885Sdim return "i386"; 260218885Sdim case 4: 261218885Sdim switch (Model) { 262218885Sdim case 0: // Intel486 DX processors 263218885Sdim case 1: // Intel486 DX processors 264218885Sdim case 2: // Intel486 SX processors 265218885Sdim case 3: // Intel487 processors, IntelDX2 OverDrive processors, 266218885Sdim // IntelDX2 processors 267218885Sdim case 4: // Intel486 SL processor 268218885Sdim case 5: // IntelSX2 processors 269218885Sdim case 7: // Write-Back Enhanced IntelDX2 processors 270218885Sdim case 8: // IntelDX4 OverDrive processors, IntelDX4 processors 271218885Sdim default: return "i486"; 272218885Sdim } 273218885Sdim case 5: 274218885Sdim switch (Model) { 275218885Sdim case 1: // Pentium OverDrive processor for Pentium processor (60, 66), 276218885Sdim // Pentium processors (60, 66) 277218885Sdim case 2: // Pentium OverDrive processor for Pentium processor (75, 90, 278218885Sdim // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133, 279218885Sdim // 150, 166, 200) 280218885Sdim case 3: // Pentium OverDrive processors for Intel486 processor-based 281218885Sdim // systems 282218885Sdim return "pentium"; 283218885Sdim 284218885Sdim case 4: // Pentium OverDrive processor with MMX technology for Pentium 285218885Sdim // processor (75, 90, 100, 120, 133), Pentium processor with 286218885Sdim // MMX technology (166, 200) 287218885Sdim return "pentium-mmx"; 288218885Sdim 289218885Sdim default: return "pentium"; 290218885Sdim } 291218885Sdim case 6: 292218885Sdim switch (Model) { 293218885Sdim case 1: // Pentium Pro processor 294218885Sdim return "pentiumpro"; 295218885Sdim 296218885Sdim case 3: // Intel Pentium II OverDrive processor, Pentium II processor, 297218885Sdim // model 03 298218885Sdim case 5: // Pentium II processor, model 05, Pentium II Xeon processor, 299218885Sdim // model 05, and Intel Celeron processor, model 05 300218885Sdim case 6: // Celeron processor, model 06 301218885Sdim return "pentium2"; 302218885Sdim 303218885Sdim case 7: // Pentium III processor, model 07, and Pentium III Xeon 304218885Sdim // processor, model 07 305218885Sdim case 8: // Pentium III processor, model 08, Pentium III Xeon processor, 306218885Sdim // model 08, and Celeron processor, model 08 307218885Sdim case 10: // Pentium III Xeon processor, model 0Ah 308218885Sdim case 11: // Pentium III processor, model 0Bh 309218885Sdim return "pentium3"; 310218885Sdim 311218885Sdim case 9: // Intel Pentium M processor, Intel Celeron M processor model 09. 312218885Sdim case 13: // Intel Pentium M processor, Intel Celeron M processor, model 313218885Sdim // 0Dh. All processors are manufactured using the 90 nm process. 314288943Sdim case 21: // Intel EP80579 Integrated Processor and Intel EP80579 315288943Sdim // Integrated Processor with Intel QuickAssist Technology 316218885Sdim return "pentium-m"; 317218885Sdim 318218885Sdim case 14: // Intel Core Duo processor, Intel Core Solo processor, model 319218885Sdim // 0Eh. All processors are manufactured using the 65 nm process. 320218885Sdim return "yonah"; 321218885Sdim 322218885Sdim case 15: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile 323218885Sdim // processor, Intel Core 2 Quad processor, Intel Core 2 Quad 324218885Sdim // mobile processor, Intel Core 2 Extreme processor, Intel 325218885Sdim // Pentium Dual-Core processor, Intel Xeon processor, model 326218885Sdim // 0Fh. All processors are manufactured using the 65 nm process. 327218885Sdim case 22: // Intel Celeron processor model 16h. All processors are 328218885Sdim // manufactured using the 65 nm process 329218885Sdim return "core2"; 330218885Sdim 331218885Sdim case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model 332218885Sdim // 17h. All processors are manufactured using the 45 nm process. 333218885Sdim // 334218885Sdim // 45nm: Penryn , Wolfdale, Yorkfield (XE) 335288943Sdim case 29: // Intel Xeon processor MP. All processors are manufactured using 336288943Sdim // the 45 nm process. 337288943Sdim return "penryn"; 338218885Sdim 339218885Sdim case 26: // Intel Core i7 processor and Intel Xeon processor. All 340218885Sdim // processors are manufactured using the 45 nm process. 341218885Sdim case 30: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. 342218885Sdim // As found in a Summer 2010 model iMac. 343288943Sdim case 46: // Nehalem EX 344288943Sdim return "nehalem"; 345218885Sdim case 37: // Intel Core i7, laptop version. 346226633Sdim case 44: // Intel Core i7 processor and Intel Xeon processor. All 347226633Sdim // processors are manufactured using the 32 nm process. 348243830Sdim case 47: // Westmere EX 349288943Sdim return "westmere"; 350224145Sdim 351224145Sdim // SandyBridge: 352224145Sdim case 42: // Intel Core i7 processor. All processors are manufactured 353224145Sdim // using the 32 nm process. 354223017Sdim case 45: 355288943Sdim return "sandybridge"; 356218885Sdim 357239462Sdim // Ivy Bridge: 358239462Sdim case 58: 359261991Sdim case 62: // Ivy Bridge EP 360288943Sdim return "ivybridge"; 361239462Sdim 362261991Sdim // Haswell: 363261991Sdim case 60: 364261991Sdim case 63: 365261991Sdim case 69: 366261991Sdim case 70: 367288943Sdim return "haswell"; 368261991Sdim 369288943Sdim // Broadwell: 370288943Sdim case 61: 371296417Sdim case 71: 372288943Sdim return "broadwell"; 373288943Sdim 374296417Sdim // Skylake: 375296417Sdim case 78: 376296417Sdim case 94: 377296417Sdim return "skylake"; 378296417Sdim 379239462Sdim case 28: // Most 45 nm Intel Atom processors 380239462Sdim case 38: // 45 nm Atom Lincroft 381239462Sdim case 39: // 32 nm Atom Medfield 382239462Sdim case 53: // 32 nm Atom Midview 383239462Sdim case 54: // 32 nm Atom Midview 384288943Sdim return "bonnell"; 385218885Sdim 386261991Sdim // Atom Silvermont codes from the Intel software optimization guide. 387261991Sdim case 55: 388261991Sdim case 74: 389261991Sdim case 77: 390296417Sdim case 90: 391296417Sdim case 93: 392288943Sdim return "silvermont"; 393261991Sdim 394288943Sdim default: // Unknown family 6 CPU, try to guess. 395288943Sdim if (HasAVX512) 396288943Sdim return "knl"; 397288943Sdim if (HasADX) 398288943Sdim return "broadwell"; 399288943Sdim if (HasAVX2) 400288943Sdim return "haswell"; 401288943Sdim if (HasAVX) 402288943Sdim return "sandybridge"; 403288943Sdim if (HasSSE42) 404288943Sdim return HasMOVBE ? "silvermont" : "nehalem"; 405288943Sdim if (HasSSE41) 406288943Sdim return "penryn"; 407288943Sdim if (HasSSSE3) 408288943Sdim return HasMOVBE ? "bonnell" : "core2"; 409288943Sdim if (Em64T) 410288943Sdim return "x86-64"; 411288943Sdim if (HasSSE2) 412288943Sdim return "pentium-m"; 413288943Sdim if (HasSSE) 414288943Sdim return "pentium3"; 415288943Sdim if (HasMMX) 416288943Sdim return "pentium2"; 417288943Sdim return "pentiumpro"; 418218885Sdim } 419218885Sdim case 15: { 420218885Sdim switch (Model) { 421218885Sdim case 0: // Pentium 4 processor, Intel Xeon processor. All processors are 422218885Sdim // model 00h and manufactured using the 0.18 micron process. 423218885Sdim case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon 424218885Sdim // processor MP, and Intel Celeron processor. All processors are 425218885Sdim // model 01h and manufactured using the 0.18 micron process. 426218885Sdim case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M, 427218885Sdim // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron 428218885Sdim // processor, and Mobile Intel Celeron processor. All processors 429218885Sdim // are model 02h and manufactured using the 0.13 micron process. 430218885Sdim return (Em64T) ? "x86-64" : "pentium4"; 431218885Sdim 432218885Sdim case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D 433218885Sdim // processor. All processors are model 03h and manufactured using 434218885Sdim // the 90 nm process. 435218885Sdim case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition, 436218885Sdim // Pentium D processor, Intel Xeon processor, Intel Xeon 437218885Sdim // processor MP, Intel Celeron D processor. All processors are 438218885Sdim // model 04h and manufactured using the 90 nm process. 439218885Sdim case 6: // Pentium 4 processor, Pentium D processor, Pentium processor 440218885Sdim // Extreme Edition, Intel Xeon processor, Intel Xeon processor 441218885Sdim // MP, Intel Celeron D processor. All processors are model 06h 442218885Sdim // and manufactured using the 65 nm process. 443218885Sdim return (Em64T) ? "nocona" : "prescott"; 444218885Sdim 445218885Sdim default: 446218885Sdim return (Em64T) ? "x86-64" : "pentium4"; 447218885Sdim } 448218885Sdim } 449218885Sdim 450218885Sdim default: 451218885Sdim return "generic"; 452218885Sdim } 453218885Sdim } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) { 454218885Sdim // FIXME: this poorly matches the generated SubtargetFeatureKV table. There 455218885Sdim // appears to be no way to generate the wide variety of AMD-specific targets 456218885Sdim // from the information returned from CPUID. 457218885Sdim switch (Family) { 458218885Sdim case 4: 459218885Sdim return "i486"; 460218885Sdim case 5: 461218885Sdim switch (Model) { 462218885Sdim case 6: 463218885Sdim case 7: return "k6"; 464218885Sdim case 8: return "k6-2"; 465218885Sdim case 9: 466218885Sdim case 13: return "k6-3"; 467241427Sdim case 10: return "geode"; 468218885Sdim default: return "pentium"; 469218885Sdim } 470218885Sdim case 6: 471218885Sdim switch (Model) { 472218885Sdim case 4: return "athlon-tbird"; 473218885Sdim case 6: 474218885Sdim case 7: 475218885Sdim case 8: return "athlon-mp"; 476218885Sdim case 10: return "athlon-xp"; 477218885Sdim default: return "athlon"; 478218885Sdim } 479218885Sdim case 15: 480218885Sdim if (HasSSE3) 481218885Sdim return "k8-sse3"; 482218885Sdim switch (Model) { 483218885Sdim case 1: return "opteron"; 484218885Sdim case 5: return "athlon-fx"; // also opteron 485218885Sdim default: return "athlon64"; 486218885Sdim } 487218885Sdim case 16: 488218885Sdim return "amdfam10"; 489234353Sdim case 20: 490234353Sdim return "btver1"; 491234353Sdim case 21: 492251662Sdim if (!HasAVX) // If the OS doesn't support AVX provide a sane fallback. 493251662Sdim return "btver1"; 494276479Sdim if (Model >= 0x50) 495276479Sdim return "bdver4"; // 50h-6Fh: Excavator 496261991Sdim if (Model >= 0x30) 497261991Sdim return "bdver3"; // 30h-3Fh: Steamroller 498276479Sdim if (Model >= 0x10 || HasTBM) 499261991Sdim return "bdver2"; // 10h-1Fh: Piledriver 500261991Sdim return "bdver1"; // 00h-0Fh: Bulldozer 501251662Sdim case 22: 502251662Sdim if (!HasAVX) // If the OS doesn't support AVX provide a sane fallback. 503251662Sdim return "btver1"; 504251662Sdim return "btver2"; 505218885Sdim default: 506218885Sdim return "generic"; 507218885Sdim } 508218885Sdim } 509218885Sdim return "generic"; 510218885Sdim} 511239462Sdim#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__)) 512276479SdimStringRef sys::getHostCPUName() { 513239462Sdim host_basic_info_data_t hostInfo; 514239462Sdim mach_msg_type_number_t infoCount; 515239462Sdim 516239462Sdim infoCount = HOST_BASIC_INFO_COUNT; 517239462Sdim host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, 518239462Sdim &infoCount); 519239462Sdim 520239462Sdim if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic"; 521239462Sdim 522239462Sdim switch(hostInfo.cpu_subtype) { 523239462Sdim case CPU_SUBTYPE_POWERPC_601: return "601"; 524239462Sdim case CPU_SUBTYPE_POWERPC_602: return "602"; 525239462Sdim case CPU_SUBTYPE_POWERPC_603: return "603"; 526239462Sdim case CPU_SUBTYPE_POWERPC_603e: return "603e"; 527239462Sdim case CPU_SUBTYPE_POWERPC_603ev: return "603ev"; 528239462Sdim case CPU_SUBTYPE_POWERPC_604: return "604"; 529239462Sdim case CPU_SUBTYPE_POWERPC_604e: return "604e"; 530239462Sdim case CPU_SUBTYPE_POWERPC_620: return "620"; 531239462Sdim case CPU_SUBTYPE_POWERPC_750: return "750"; 532239462Sdim case CPU_SUBTYPE_POWERPC_7400: return "7400"; 533239462Sdim case CPU_SUBTYPE_POWERPC_7450: return "7450"; 534239462Sdim case CPU_SUBTYPE_POWERPC_970: return "970"; 535239462Sdim default: ; 536239462Sdim } 537239462Sdim 538239462Sdim return "generic"; 539239462Sdim} 540239462Sdim#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__)) 541276479SdimStringRef sys::getHostCPUName() { 542239462Sdim // Access to the Processor Version Register (PVR) on PowerPC is privileged, 543239462Sdim // and so we must use an operating-system interface to determine the current 544239462Sdim // processor type. On Linux, this is exposed through the /proc/cpuinfo file. 545239462Sdim const char *generic = "generic"; 546239462Sdim 547239462Sdim // The cpu line is second (after the 'processor: 0' line), so if this 548239462Sdim // buffer is too small then something has changed (or is wrong). 549239462Sdim char buffer[1024]; 550280031Sdim ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); 551280031Sdim if (CPUInfoSize == -1) 552280031Sdim return generic; 553239462Sdim 554239462Sdim const char *CPUInfoStart = buffer; 555239462Sdim const char *CPUInfoEnd = buffer + CPUInfoSize; 556239462Sdim 557239462Sdim const char *CIP = CPUInfoStart; 558239462Sdim 559239462Sdim const char *CPUStart = 0; 560239462Sdim size_t CPULen = 0; 561239462Sdim 562239462Sdim // We need to find the first line which starts with cpu, spaces, and a colon. 563239462Sdim // After the colon, there may be some additional spaces and then the cpu type. 564239462Sdim while (CIP < CPUInfoEnd && CPUStart == 0) { 565239462Sdim if (CIP < CPUInfoEnd && *CIP == '\n') 566239462Sdim ++CIP; 567239462Sdim 568239462Sdim if (CIP < CPUInfoEnd && *CIP == 'c') { 569239462Sdim ++CIP; 570239462Sdim if (CIP < CPUInfoEnd && *CIP == 'p') { 571239462Sdim ++CIP; 572239462Sdim if (CIP < CPUInfoEnd && *CIP == 'u') { 573239462Sdim ++CIP; 574239462Sdim while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) 575239462Sdim ++CIP; 576239462Sdim 577239462Sdim if (CIP < CPUInfoEnd && *CIP == ':') { 578239462Sdim ++CIP; 579239462Sdim while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) 580239462Sdim ++CIP; 581239462Sdim 582239462Sdim if (CIP < CPUInfoEnd) { 583239462Sdim CPUStart = CIP; 584239462Sdim while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' && 585239462Sdim *CIP != ',' && *CIP != '\n')) 586239462Sdim ++CIP; 587239462Sdim CPULen = CIP - CPUStart; 588239462Sdim } 589239462Sdim } 590239462Sdim } 591239462Sdim } 592239462Sdim } 593239462Sdim 594239462Sdim if (CPUStart == 0) 595239462Sdim while (CIP < CPUInfoEnd && *CIP != '\n') 596239462Sdim ++CIP; 597239462Sdim } 598239462Sdim 599239462Sdim if (CPUStart == 0) 600239462Sdim return generic; 601239462Sdim 602239462Sdim return StringSwitch<const char *>(StringRef(CPUStart, CPULen)) 603239462Sdim .Case("604e", "604e") 604239462Sdim .Case("604", "604") 605239462Sdim .Case("7400", "7400") 606239462Sdim .Case("7410", "7400") 607239462Sdim .Case("7447", "7400") 608239462Sdim .Case("7455", "7450") 609239462Sdim .Case("G4", "g4") 610239462Sdim .Case("POWER4", "970") 611239462Sdim .Case("PPC970FX", "970") 612239462Sdim .Case("PPC970MP", "970") 613239462Sdim .Case("G5", "g5") 614239462Sdim .Case("POWER5", "g5") 615239462Sdim .Case("A2", "a2") 616239462Sdim .Case("POWER6", "pwr6") 617239462Sdim .Case("POWER7", "pwr7") 618276479Sdim .Case("POWER8", "pwr8") 619276479Sdim .Case("POWER8E", "pwr8") 620239462Sdim .Default(generic); 621239462Sdim} 622239462Sdim#elif defined(__linux__) && defined(__arm__) 623276479SdimStringRef sys::getHostCPUName() { 624239462Sdim // The cpuid register on arm is not accessible from user space. On Linux, 625239462Sdim // it is exposed through the /proc/cpuinfo file. 626239462Sdim 627239462Sdim // Read 1024 bytes from /proc/cpuinfo, which should contain the CPU part line 628239462Sdim // in all cases. 629239462Sdim char buffer[1024]; 630280031Sdim ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); 631280031Sdim if (CPUInfoSize == -1) 632280031Sdim return "generic"; 633239462Sdim 634239462Sdim StringRef Str(buffer, CPUInfoSize); 635239462Sdim 636239462Sdim SmallVector<StringRef, 32> Lines; 637239462Sdim Str.split(Lines, "\n"); 638239462Sdim 639239462Sdim // Look for the CPU implementer line. 640239462Sdim StringRef Implementer; 641239462Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 642239462Sdim if (Lines[I].startswith("CPU implementer")) 643239462Sdim Implementer = Lines[I].substr(15).ltrim("\t :"); 644239462Sdim 645239462Sdim if (Implementer == "0x41") // ARM Ltd. 646239462Sdim // Look for the CPU part line. 647239462Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 648239462Sdim if (Lines[I].startswith("CPU part")) 649239462Sdim // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The 650239462Sdim // values correspond to the "Part number" in the CP15/c0 register. The 651239462Sdim // contents are specified in the various processor manuals. 652239462Sdim return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) 653239462Sdim .Case("0x926", "arm926ej-s") 654239462Sdim .Case("0xb02", "mpcore") 655239462Sdim .Case("0xb36", "arm1136j-s") 656239462Sdim .Case("0xb56", "arm1156t2-s") 657239462Sdim .Case("0xb76", "arm1176jz-s") 658239462Sdim .Case("0xc08", "cortex-a8") 659239462Sdim .Case("0xc09", "cortex-a9") 660243830Sdim .Case("0xc0f", "cortex-a15") 661239462Sdim .Case("0xc20", "cortex-m0") 662239462Sdim .Case("0xc23", "cortex-m3") 663239462Sdim .Case("0xc24", "cortex-m4") 664239462Sdim .Default("generic"); 665239462Sdim 666276479Sdim if (Implementer == "0x51") // Qualcomm Technologies, Inc. 667276479Sdim // Look for the CPU part line. 668276479Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 669276479Sdim if (Lines[I].startswith("CPU part")) 670276479Sdim // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The 671276479Sdim // values correspond to the "Part number" in the CP15/c0 register. The 672276479Sdim // contents are specified in the various processor manuals. 673276479Sdim return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) 674276479Sdim .Case("0x06f", "krait") // APQ8064 675276479Sdim .Default("generic"); 676276479Sdim 677239462Sdim return "generic"; 678239462Sdim} 679261991Sdim#elif defined(__linux__) && defined(__s390x__) 680276479SdimStringRef sys::getHostCPUName() { 681261991Sdim // STIDP is a privileged operation, so use /proc/cpuinfo instead. 682261991Sdim 683261991Sdim // The "processor 0:" line comes after a fair amount of other information, 684261991Sdim // including a cache breakdown, but this should be plenty. 685261991Sdim char buffer[2048]; 686280031Sdim ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); 687280031Sdim if (CPUInfoSize == -1) 688280031Sdim return "generic"; 689261991Sdim 690261991Sdim StringRef Str(buffer, CPUInfoSize); 691261991Sdim SmallVector<StringRef, 32> Lines; 692261991Sdim Str.split(Lines, "\n"); 693288943Sdim 694288943Sdim // Look for the CPU features. 695288943Sdim SmallVector<StringRef, 32> CPUFeatures; 696288943Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 697288943Sdim if (Lines[I].startswith("features")) { 698288943Sdim size_t Pos = Lines[I].find(":"); 699288943Sdim if (Pos != StringRef::npos) { 700296417Sdim Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' '); 701288943Sdim break; 702288943Sdim } 703288943Sdim } 704288943Sdim 705288943Sdim // We need to check for the presence of vector support independently of 706288943Sdim // the machine type, since we may only use the vector register set when 707288943Sdim // supported by the kernel (and hypervisor). 708288943Sdim bool HaveVectorSupport = false; 709288943Sdim for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { 710288943Sdim if (CPUFeatures[I] == "vx") 711288943Sdim HaveVectorSupport = true; 712288943Sdim } 713288943Sdim 714288943Sdim // Now check the processor machine type. 715261991Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) { 716261991Sdim if (Lines[I].startswith("processor ")) { 717261991Sdim size_t Pos = Lines[I].find("machine = "); 718261991Sdim if (Pos != StringRef::npos) { 719261991Sdim Pos += sizeof("machine = ") - 1; 720261991Sdim unsigned int Id; 721261991Sdim if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) { 722288943Sdim if (Id >= 2964 && HaveVectorSupport) 723288943Sdim return "z13"; 724261991Sdim if (Id >= 2827) 725261991Sdim return "zEC12"; 726261991Sdim if (Id >= 2817) 727261991Sdim return "z196"; 728261991Sdim } 729261991Sdim } 730261991Sdim break; 731261991Sdim } 732261991Sdim } 733261991Sdim 734261991Sdim return "generic"; 735261991Sdim} 736218885Sdim#else 737276479SdimStringRef sys::getHostCPUName() { 738218885Sdim return "generic"; 739218885Sdim} 740218885Sdim#endif 741218885Sdim 742288943Sdim#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\ 743288943Sdim || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) 744249423Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features) { 745288943Sdim unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; 746288943Sdim unsigned MaxLevel; 747288943Sdim union { 748288943Sdim unsigned u[3]; 749288943Sdim char c[12]; 750288943Sdim } text; 751288943Sdim 752288943Sdim if (GetX86CpuIDAndInfo(0, &MaxLevel, text.u+0, text.u+2, text.u+1) || 753288943Sdim MaxLevel < 1) 754288943Sdim return false; 755288943Sdim 756288943Sdim GetX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX); 757288943Sdim 758288943Sdim Features["cmov"] = (EDX >> 15) & 1; 759288943Sdim Features["mmx"] = (EDX >> 23) & 1; 760288943Sdim Features["sse"] = (EDX >> 25) & 1; 761288943Sdim Features["sse2"] = (EDX >> 26) & 1; 762288943Sdim Features["sse3"] = (ECX >> 0) & 1; 763288943Sdim Features["ssse3"] = (ECX >> 9) & 1; 764288943Sdim Features["sse4.1"] = (ECX >> 19) & 1; 765288943Sdim Features["sse4.2"] = (ECX >> 20) & 1; 766288943Sdim 767288943Sdim Features["pclmul"] = (ECX >> 1) & 1; 768288943Sdim Features["cx16"] = (ECX >> 13) & 1; 769288943Sdim Features["movbe"] = (ECX >> 22) & 1; 770288943Sdim Features["popcnt"] = (ECX >> 23) & 1; 771288943Sdim Features["aes"] = (ECX >> 25) & 1; 772288943Sdim Features["rdrnd"] = (ECX >> 30) & 1; 773288943Sdim 774288943Sdim // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV 775288943Sdim // indicates that the AVX registers will be saved and restored on context 776288943Sdim // switch, then we have full AVX support. 777296417Sdim bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) && 778296417Sdim !GetX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6); 779296417Sdim Features["avx"] = HasAVXSave; 780296417Sdim Features["fma"] = HasAVXSave && (ECX >> 12) & 1; 781296417Sdim Features["f16c"] = HasAVXSave && (ECX >> 29) & 1; 782288943Sdim 783296417Sdim // Only enable XSAVE if OS has enabled support for saving YMM state. 784296417Sdim Features["xsave"] = HasAVXSave && (ECX >> 26) & 1; 785296417Sdim 786288943Sdim // AVX512 requires additional context to be saved by the OS. 787296417Sdim bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0); 788288943Sdim 789288943Sdim unsigned MaxExtLevel; 790288943Sdim GetX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX); 791288943Sdim 792288943Sdim bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 && 793288943Sdim !GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); 794288943Sdim Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1); 795288943Sdim Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1); 796288943Sdim Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1); 797296417Sdim Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave; 798296417Sdim Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave; 799288943Sdim Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1); 800288943Sdim 801288943Sdim bool HasLeaf7 = MaxLevel >= 7 && 802288943Sdim !GetX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); 803288943Sdim 804288943Sdim // AVX2 is only supported if we have the OS save support from AVX. 805296417Sdim Features["avx2"] = HasAVXSave && HasLeaf7 && ((EBX >> 5) & 1); 806288943Sdim 807288943Sdim Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1); 808288943Sdim Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1); 809288943Sdim Features["hle"] = HasLeaf7 && ((EBX >> 4) & 1); 810288943Sdim Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1); 811288943Sdim Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1); 812288943Sdim Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1); 813288943Sdim Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1); 814288943Sdim Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1); 815296417Sdim // Enable protection keys 816296417Sdim Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1); 817288943Sdim 818288943Sdim // AVX512 is only supported if the OS supports the context save for it. 819288943Sdim Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save; 820288943Sdim Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save; 821288943Sdim Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save; 822288943Sdim Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save; 823288943Sdim Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save; 824288943Sdim Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save; 825288943Sdim Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save; 826288943Sdim 827296417Sdim bool HasLeafD = MaxLevel >= 0xd && 828296417Sdim !GetX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX); 829296417Sdim 830296417Sdim // Only enable XSAVE if OS has enabled support for saving YMM state. 831296417Sdim Features["xsaveopt"] = HasAVXSave && HasLeafD && ((EAX >> 0) & 1); 832296417Sdim Features["xsavec"] = HasAVXSave && HasLeafD && ((EAX >> 1) & 1); 833296417Sdim Features["xsaves"] = HasAVXSave && HasLeafD && ((EAX >> 3) & 1); 834296417Sdim 835288943Sdim return true; 836288943Sdim} 837288943Sdim#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__)) 838288943Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features) { 839249423Sdim // Read 1024 bytes from /proc/cpuinfo, which should contain the Features line 840249423Sdim // in all cases. 841249423Sdim char buffer[1024]; 842280031Sdim ssize_t CPUInfoSize = readCpuInfo(buffer, sizeof(buffer)); 843280031Sdim if (CPUInfoSize == -1) 844280031Sdim return false; 845249423Sdim 846249423Sdim StringRef Str(buffer, CPUInfoSize); 847249423Sdim 848249423Sdim SmallVector<StringRef, 32> Lines; 849249423Sdim Str.split(Lines, "\n"); 850249423Sdim 851261991Sdim SmallVector<StringRef, 32> CPUFeatures; 852261991Sdim 853261991Sdim // Look for the CPU features. 854249423Sdim for (unsigned I = 0, E = Lines.size(); I != E; ++I) 855261991Sdim if (Lines[I].startswith("Features")) { 856296417Sdim Lines[I].split(CPUFeatures, ' '); 857261991Sdim break; 858261991Sdim } 859249423Sdim 860276479Sdim#if defined(__aarch64__) 861276479Sdim // Keep track of which crypto features we have seen 862276479Sdim enum { 863276479Sdim CAP_AES = 0x1, 864276479Sdim CAP_PMULL = 0x2, 865276479Sdim CAP_SHA1 = 0x4, 866276479Sdim CAP_SHA2 = 0x8 867276479Sdim }; 868276479Sdim uint32_t crypto = 0; 869276479Sdim#endif 870276479Sdim 871261991Sdim for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { 872261991Sdim StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I]) 873276479Sdim#if defined(__aarch64__) 874276479Sdim .Case("asimd", "neon") 875276479Sdim .Case("fp", "fp-armv8") 876276479Sdim .Case("crc32", "crc") 877276479Sdim#else 878261991Sdim .Case("half", "fp16") 879261991Sdim .Case("neon", "neon") 880261991Sdim .Case("vfpv3", "vfp3") 881261991Sdim .Case("vfpv3d16", "d16") 882261991Sdim .Case("vfpv4", "vfp4") 883261991Sdim .Case("idiva", "hwdiv-arm") 884261991Sdim .Case("idivt", "hwdiv") 885276479Sdim#endif 886261991Sdim .Default(""); 887249423Sdim 888276479Sdim#if defined(__aarch64__) 889276479Sdim // We need to check crypto separately since we need all of the crypto 890276479Sdim // extensions to enable the subtarget feature 891276479Sdim if (CPUFeatures[I] == "aes") 892276479Sdim crypto |= CAP_AES; 893276479Sdim else if (CPUFeatures[I] == "pmull") 894276479Sdim crypto |= CAP_PMULL; 895276479Sdim else if (CPUFeatures[I] == "sha1") 896276479Sdim crypto |= CAP_SHA1; 897276479Sdim else if (CPUFeatures[I] == "sha2") 898276479Sdim crypto |= CAP_SHA2; 899276479Sdim#endif 900276479Sdim 901261991Sdim if (LLVMFeatureStr != "") 902280031Sdim Features[LLVMFeatureStr] = true; 903249423Sdim } 904249423Sdim 905276479Sdim#if defined(__aarch64__) 906276479Sdim // If we have all crypto bits we can add the feature 907276479Sdim if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2)) 908280031Sdim Features["crypto"] = true; 909276479Sdim#endif 910276479Sdim 911261991Sdim return true; 912249423Sdim} 913249423Sdim#else 914218885Sdimbool sys::getHostCPUFeatures(StringMap<bool> &Features){ 915218885Sdim return false; 916218885Sdim} 917249423Sdim#endif 918249423Sdim 919249423Sdimstd::string sys::getProcessTriple() { 920261991Sdim Triple PT(Triple::normalize(LLVM_HOST_TRIPLE)); 921249423Sdim 922249423Sdim if (sizeof(void *) == 8 && PT.isArch32Bit()) 923249423Sdim PT = PT.get64BitArchVariant(); 924249423Sdim if (sizeof(void *) == 4 && PT.isArch64Bit()) 925249423Sdim PT = PT.get32BitArchVariant(); 926249423Sdim 927249423Sdim return PT.str(); 928249423Sdim} 929