Host.cpp revision 4db738ae9862a2d00e2dca5b8fbf9d4dfa706142
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/ADT/StringRef.h"
15#include "llvm/ADT/StringSwitch.h"
16#include "llvm/Support/DataStream.h"
17#include "llvm/Support/Debug.h"
18#include "llvm/Support/Host.h"
19#include "llvm/Support/raw_ostream.h"
20#include "llvm/Config/config.h"
21#include <string.h>
22
23// Include the platform-specific parts of this class.
24#ifdef LLVM_ON_UNIX
25#include "Unix/Host.inc"
26#endif
27#ifdef LLVM_ON_WIN32
28#include "Windows/Host.inc"
29#endif
30#ifdef _MSC_VER
31#include <intrin.h>
32#endif
33#if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
34#include <mach/mach.h>
35#include <mach/mach_host.h>
36#include <mach/host_info.h>
37#include <mach/machine.h>
38#endif
39
40//===----------------------------------------------------------------------===//
41//
42//  Implementations of the CPU detection routines
43//
44//===----------------------------------------------------------------------===//
45
46using namespace llvm;
47
48#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\
49 || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
50
51/// GetX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
52/// specified arguments.  If we can't run cpuid on the host, return true.
53static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX,
54                            unsigned *rEBX, unsigned *rECX, unsigned *rEDX) {
55#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
56  #if defined(__GNUC__)
57    // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
58    asm ("movq\t%%rbx, %%rsi\n\t"
59         "cpuid\n\t"
60         "xchgq\t%%rbx, %%rsi\n\t"
61         : "=a" (*rEAX),
62           "=S" (*rEBX),
63           "=c" (*rECX),
64           "=d" (*rEDX)
65         :  "a" (value));
66    return false;
67  #elif defined(_MSC_VER)
68    int registers[4];
69    __cpuid(registers, value);
70    *rEAX = registers[0];
71    *rEBX = registers[1];
72    *rECX = registers[2];
73    *rEDX = registers[3];
74    return false;
75  #else
76    return true;
77  #endif
78#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
79  #if defined(__GNUC__)
80    asm ("movl\t%%ebx, %%esi\n\t"
81         "cpuid\n\t"
82         "xchgl\t%%ebx, %%esi\n\t"
83         : "=a" (*rEAX),
84           "=S" (*rEBX),
85           "=c" (*rECX),
86           "=d" (*rEDX)
87         :  "a" (value));
88    return false;
89  #elif defined(_MSC_VER)
90    __asm {
91      mov   eax,value
92      cpuid
93      mov   esi,rEAX
94      mov   dword ptr [esi],eax
95      mov   esi,rEBX
96      mov   dword ptr [esi],ebx
97      mov   esi,rECX
98      mov   dword ptr [esi],ecx
99      mov   esi,rEDX
100      mov   dword ptr [esi],edx
101    }
102    return false;
103// pedantic #else returns to appease -Wunreachable-code (so we don't generate
104// postprocessed code that looks like "return true; return false;")
105  #else
106    return true;
107  #endif
108#else
109  return true;
110#endif
111}
112
113static void DetectX86FamilyModel(unsigned EAX, unsigned &Family,
114                                 unsigned &Model) {
115  Family = (EAX >> 8) & 0xf; // Bits 8 - 11
116  Model  = (EAX >> 4) & 0xf; // Bits 4 - 7
117  if (Family == 6 || Family == 0xf) {
118    if (Family == 0xf)
119      // Examine extended family ID if family ID is F.
120      Family += (EAX >> 20) & 0xff;    // Bits 20 - 27
121    // Examine extended model ID if family ID is 6 or F.
122    Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
123  }
124}
125
126std::string sys::getHostCPUName() {
127  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
128  if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
129    return "generic";
130  unsigned Family = 0;
131  unsigned Model  = 0;
132  DetectX86FamilyModel(EAX, Family, Model);
133
134  bool HasSSE3 = (ECX & 0x1);
135  GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
136  bool Em64T = (EDX >> 29) & 0x1;
137
138  union {
139    unsigned u[3];
140    char     c[12];
141  } text;
142
143  GetX86CpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
144  if (memcmp(text.c, "GenuineIntel", 12) == 0) {
145    switch (Family) {
146    case 3:
147      return "i386";
148    case 4:
149      switch (Model) {
150      case 0: // Intel486 DX processors
151      case 1: // Intel486 DX processors
152      case 2: // Intel486 SX processors
153      case 3: // Intel487 processors, IntelDX2 OverDrive processors,
154              // IntelDX2 processors
155      case 4: // Intel486 SL processor
156      case 5: // IntelSX2 processors
157      case 7: // Write-Back Enhanced IntelDX2 processors
158      case 8: // IntelDX4 OverDrive processors, IntelDX4 processors
159      default: return "i486";
160      }
161    case 5:
162      switch (Model) {
163      case  1: // Pentium OverDrive processor for Pentium processor (60, 66),
164               // Pentium processors (60, 66)
165      case  2: // Pentium OverDrive processor for Pentium processor (75, 90,
166               // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133,
167               // 150, 166, 200)
168      case  3: // Pentium OverDrive processors for Intel486 processor-based
169               // systems
170        return "pentium";
171
172      case  4: // Pentium OverDrive processor with MMX technology for Pentium
173               // processor (75, 90, 100, 120, 133), Pentium processor with
174               // MMX technology (166, 200)
175        return "pentium-mmx";
176
177      default: return "pentium";
178      }
179    case 6:
180      switch (Model) {
181      case  1: // Pentium Pro processor
182        return "pentiumpro";
183
184      case  3: // Intel Pentium II OverDrive processor, Pentium II processor,
185               // model 03
186      case  5: // Pentium II processor, model 05, Pentium II Xeon processor,
187               // model 05, and Intel Celeron processor, model 05
188      case  6: // Celeron processor, model 06
189        return "pentium2";
190
191      case  7: // Pentium III processor, model 07, and Pentium III Xeon
192               // processor, model 07
193      case  8: // Pentium III processor, model 08, Pentium III Xeon processor,
194               // model 08, and Celeron processor, model 08
195      case 10: // Pentium III Xeon processor, model 0Ah
196      case 11: // Pentium III processor, model 0Bh
197        return "pentium3";
198
199      case  9: // Intel Pentium M processor, Intel Celeron M processor model 09.
200      case 13: // Intel Pentium M processor, Intel Celeron M processor, model
201               // 0Dh. All processors are manufactured using the 90 nm process.
202        return "pentium-m";
203
204      case 14: // Intel Core Duo processor, Intel Core Solo processor, model
205               // 0Eh. All processors are manufactured using the 65 nm process.
206        return "yonah";
207
208      case 15: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
209               // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
210               // mobile processor, Intel Core 2 Extreme processor, Intel
211               // Pentium Dual-Core processor, Intel Xeon processor, model
212               // 0Fh. All processors are manufactured using the 65 nm process.
213      case 22: // Intel Celeron processor model 16h. All processors are
214               // manufactured using the 65 nm process
215        return "core2";
216
217      case 21: // Intel EP80579 Integrated Processor and Intel EP80579
218               // Integrated Processor with Intel QuickAssist Technology
219        return "i686"; // FIXME: ???
220
221      case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model
222               // 17h. All processors are manufactured using the 45 nm process.
223               //
224               // 45nm: Penryn , Wolfdale, Yorkfield (XE)
225        return "penryn";
226
227      case 26: // Intel Core i7 processor and Intel Xeon processor. All
228               // processors are manufactured using the 45 nm process.
229      case 29: // Intel Xeon processor MP. All processors are manufactured using
230               // the 45 nm process.
231      case 30: // Intel(R) Core(TM) i7 CPU         870  @ 2.93GHz.
232               // As found in a Summer 2010 model iMac.
233      case 37: // Intel Core i7, laptop version.
234      case 44: // Intel Core i7 processor and Intel Xeon processor. All
235               // processors are manufactured using the 32 nm process.
236        return "corei7";
237
238      // SandyBridge:
239      case 42: // Intel Core i7 processor. All processors are manufactured
240               // using the 32 nm process.
241      case 45:
242        return "corei7-avx";
243
244      // Ivy Bridge:
245      case 58:
246        return "core-avx-i";
247
248      case 28: // Most 45 nm Intel Atom processors
249      case 38: // 45 nm Atom Lincroft
250      case 39: // 32 nm Atom Medfield
251        return "atom";
252
253      default: return (Em64T) ? "x86-64" : "i686";
254      }
255    case 15: {
256      switch (Model) {
257      case  0: // Pentium 4 processor, Intel Xeon processor. All processors are
258               // model 00h and manufactured using the 0.18 micron process.
259      case  1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon
260               // processor MP, and Intel Celeron processor. All processors are
261               // model 01h and manufactured using the 0.18 micron process.
262      case  2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M,
263               // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron
264               // processor, and Mobile Intel Celeron processor. All processors
265               // are model 02h and manufactured using the 0.13 micron process.
266        return (Em64T) ? "x86-64" : "pentium4";
267
268      case  3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D
269               // processor. All processors are model 03h and manufactured using
270               // the 90 nm process.
271      case  4: // Pentium 4 processor, Pentium 4 processor Extreme Edition,
272               // Pentium D processor, Intel Xeon processor, Intel Xeon
273               // processor MP, Intel Celeron D processor. All processors are
274               // model 04h and manufactured using the 90 nm process.
275      case  6: // Pentium 4 processor, Pentium D processor, Pentium processor
276               // Extreme Edition, Intel Xeon processor, Intel Xeon processor
277               // MP, Intel Celeron D processor. All processors are model 06h
278               // and manufactured using the 65 nm process.
279        return (Em64T) ? "nocona" : "prescott";
280
281      default:
282        return (Em64T) ? "x86-64" : "pentium4";
283      }
284    }
285
286    default:
287      return "generic";
288    }
289  } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
290    // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
291    // appears to be no way to generate the wide variety of AMD-specific targets
292    // from the information returned from CPUID.
293    switch (Family) {
294      case 4:
295        return "i486";
296      case 5:
297        switch (Model) {
298        case 6:
299        case 7:  return "k6";
300        case 8:  return "k6-2";
301        case 9:
302        case 13: return "k6-3";
303        default: return "pentium";
304        }
305      case 6:
306        switch (Model) {
307        case 4:  return "athlon-tbird";
308        case 6:
309        case 7:
310        case 8:  return "athlon-mp";
311        case 10: return "athlon-xp";
312        default: return "athlon";
313        }
314      case 15:
315        if (HasSSE3)
316          return "k8-sse3";
317        switch (Model) {
318        case 1:  return "opteron";
319        case 5:  return "athlon-fx"; // also opteron
320        default: return "athlon64";
321        }
322      case 16:
323        return "amdfam10";
324      case 20:
325        return "btver1";
326      case 21:
327        return "bdver1";
328    default:
329      return "generic";
330    }
331  }
332  return "generic";
333}
334#elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__))
335std::string sys::getHostCPUName() {
336  host_basic_info_data_t hostInfo;
337  mach_msg_type_number_t infoCount;
338
339  infoCount = HOST_BASIC_INFO_COUNT;
340  host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo,
341            &infoCount);
342
343  if (hostInfo.cpu_type != CPU_TYPE_POWERPC) return "generic";
344
345  switch(hostInfo.cpu_subtype) {
346  case CPU_SUBTYPE_POWERPC_601:   return "601";
347  case CPU_SUBTYPE_POWERPC_602:   return "602";
348  case CPU_SUBTYPE_POWERPC_603:   return "603";
349  case CPU_SUBTYPE_POWERPC_603e:  return "603e";
350  case CPU_SUBTYPE_POWERPC_603ev: return "603ev";
351  case CPU_SUBTYPE_POWERPC_604:   return "604";
352  case CPU_SUBTYPE_POWERPC_604e:  return "604e";
353  case CPU_SUBTYPE_POWERPC_620:   return "620";
354  case CPU_SUBTYPE_POWERPC_750:   return "750";
355  case CPU_SUBTYPE_POWERPC_7400:  return "7400";
356  case CPU_SUBTYPE_POWERPC_7450:  return "7450";
357  case CPU_SUBTYPE_POWERPC_970:   return "970";
358  default: ;
359  }
360
361  return "generic";
362}
363#elif defined(__linux__) && (defined(__ppc__) || defined(__powerpc__))
364std::string sys::getHostCPUName() {
365  // Access to the Processor Version Register (PVR) on PowerPC is privileged,
366  // and so we must use an operating-system interface to determine the current
367  // processor type. On Linux, this is exposed through the /proc/cpuinfo file.
368  const char *generic = "generic";
369
370  // Note: We cannot mmap /proc/cpuinfo here and then process the resulting
371  // memory buffer because the 'file' has 0 size (it can be read from only
372  // as a stream).
373
374  std::string Err;
375  DataStreamer *DS = getDataFileStreamer("/proc/cpuinfo", &Err);
376  if (!DS) {
377    DEBUG(dbgs() << "Unable to open /proc/cpuinfo: " << Err << "\n");
378    return generic;
379  }
380
381  // The cpu line is second (after the 'processor: 0' line), so if this
382  // buffer is too small then something has changed (or is wrong).
383  char buffer[1024];
384  size_t CPUInfoSize = DS->GetBytes((unsigned char*) buffer, sizeof(buffer));
385  delete DS;
386
387  const char *CPUInfoStart = buffer;
388  const char *CPUInfoEnd = buffer + CPUInfoSize;
389
390  const char *CIP = CPUInfoStart;
391
392  const char *CPUStart = 0;
393  size_t CPULen = 0;
394
395  // We need to find the first line which starts with cpu, spaces, and a colon.
396  // After the colon, there may be some additional spaces and then the cpu type.
397  while (CIP < CPUInfoEnd && CPUStart == 0) {
398    if (CIP < CPUInfoEnd && *CIP == '\n')
399      ++CIP;
400
401    if (CIP < CPUInfoEnd && *CIP == 'c') {
402      ++CIP;
403      if (CIP < CPUInfoEnd && *CIP == 'p') {
404        ++CIP;
405        if (CIP < CPUInfoEnd && *CIP == 'u') {
406          ++CIP;
407          while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
408            ++CIP;
409
410          if (CIP < CPUInfoEnd && *CIP == ':') {
411            ++CIP;
412            while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t'))
413              ++CIP;
414
415            if (CIP < CPUInfoEnd) {
416              CPUStart = CIP;
417              while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' &&
418                                          *CIP != ',' && *CIP != '\n'))
419                ++CIP;
420              CPULen = CIP - CPUStart;
421            }
422          }
423        }
424      }
425    }
426
427    if (CPUStart == 0)
428      while (CIP < CPUInfoEnd && *CIP != '\n')
429        ++CIP;
430  }
431
432  if (CPUStart == 0)
433    return generic;
434
435  return StringSwitch<const char *>(StringRef(CPUStart, CPULen))
436    .Case("604e", "604e")
437    .Case("604", "604")
438    .Case("7400", "7400")
439    .Case("7410", "7400")
440    .Case("7447", "7400")
441    .Case("7455", "7450")
442    .Case("G4", "g4")
443    .Case("POWER4", "g4")
444    .Case("PPC970FX", "970")
445    .Case("PPC970MP", "970")
446    .Case("G5", "g5")
447    .Case("POWER5", "g5")
448    .Case("A2", "a2")
449    .Case("POWER6", "pwr6")
450    .Case("POWER7", "pwr7")
451    .Default(generic);
452}
453#else
454std::string sys::getHostCPUName() {
455  return "generic";
456}
457#endif
458
459bool sys::getHostCPUFeatures(StringMap<bool> &Features){
460  return false;
461}
462