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