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