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