File: | lib/Support/Host.cpp |
Warning: | line 118, column 34 Dereference of null pointer (loaded from variable 'CIP') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 file implements the operating system Host concept. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #include "llvm/Support/Host.h" | |||
15 | #include "llvm/Support/TargetParser.h" | |||
16 | #include "llvm/ADT/SmallSet.h" | |||
17 | #include "llvm/ADT/SmallVector.h" | |||
18 | #include "llvm/ADT/StringRef.h" | |||
19 | #include "llvm/ADT/StringSwitch.h" | |||
20 | #include "llvm/ADT/Triple.h" | |||
21 | #include "llvm/Config/config.h" | |||
22 | #include "llvm/Support/Debug.h" | |||
23 | #include "llvm/Support/FileSystem.h" | |||
24 | #include "llvm/Support/MemoryBuffer.h" | |||
25 | #include "llvm/Support/raw_ostream.h" | |||
26 | #include <assert.h> | |||
27 | #include <string.h> | |||
28 | ||||
29 | // Include the platform-specific parts of this class. | |||
30 | #ifdef LLVM_ON_UNIX1 | |||
31 | #include "Unix/Host.inc" | |||
32 | #endif | |||
33 | #ifdef LLVM_ON_WIN32 | |||
34 | #include "Windows/Host.inc" | |||
35 | #endif | |||
36 | #ifdef _MSC_VER | |||
37 | #include <intrin.h> | |||
38 | #endif | |||
39 | #if defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__)) | |||
40 | #include <mach/host_info.h> | |||
41 | #include <mach/mach.h> | |||
42 | #include <mach/mach_host.h> | |||
43 | #include <mach/machine.h> | |||
44 | #endif | |||
45 | ||||
46 | #define DEBUG_TYPE"host-detection" "host-detection" | |||
47 | ||||
48 | //===----------------------------------------------------------------------===// | |||
49 | // | |||
50 | // Implementations of the CPU detection routines | |||
51 | // | |||
52 | //===----------------------------------------------------------------------===// | |||
53 | ||||
54 | using namespace llvm; | |||
55 | ||||
56 | static std::unique_ptr<llvm::MemoryBuffer> | |||
57 | LLVM_ATTRIBUTE_UNUSED__attribute__((__unused__)) getProcCpuinfoContent() { | |||
58 | llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = | |||
59 | llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); | |||
60 | if (std::error_code EC = Text.getError()) { | |||
61 | llvm::errs() << "Can't read " | |||
62 | << "/proc/cpuinfo: " << EC.message() << "\n"; | |||
63 | return nullptr; | |||
64 | } | |||
65 | return std::move(*Text); | |||
66 | } | |||
67 | ||||
68 | StringRef sys::detail::getHostCPUNameForPowerPC( | |||
69 | const StringRef &ProcCpuinfoContent) { | |||
70 | // Access to the Processor Version Register (PVR) on PowerPC is privileged, | |||
71 | // and so we must use an operating-system interface to determine the current | |||
72 | // processor type. On Linux, this is exposed through the /proc/cpuinfo file. | |||
73 | const char *generic = "generic"; | |||
74 | ||||
75 | // The cpu line is second (after the 'processor: 0' line), so if this | |||
76 | // buffer is too small then something has changed (or is wrong). | |||
77 | StringRef::const_iterator CPUInfoStart = ProcCpuinfoContent.begin(); | |||
78 | StringRef::const_iterator CPUInfoEnd = ProcCpuinfoContent.end(); | |||
79 | ||||
80 | StringRef::const_iterator CIP = CPUInfoStart; | |||
81 | ||||
82 | StringRef::const_iterator CPUStart = 0; | |||
83 | size_t CPULen = 0; | |||
84 | ||||
85 | // We need to find the first line which starts with cpu, spaces, and a colon. | |||
86 | // After the colon, there may be some additional spaces and then the cpu type. | |||
87 | while (CIP < CPUInfoEnd && CPUStart == 0) { | |||
| ||||
88 | if (CIP < CPUInfoEnd && *CIP == '\n') | |||
89 | ++CIP; | |||
90 | ||||
91 | if (CIP < CPUInfoEnd && *CIP == 'c') { | |||
92 | ++CIP; | |||
93 | if (CIP < CPUInfoEnd && *CIP == 'p') { | |||
94 | ++CIP; | |||
95 | if (CIP < CPUInfoEnd && *CIP == 'u') { | |||
96 | ++CIP; | |||
97 | while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) | |||
98 | ++CIP; | |||
99 | ||||
100 | if (CIP < CPUInfoEnd && *CIP == ':') { | |||
101 | ++CIP; | |||
102 | while (CIP < CPUInfoEnd && (*CIP == ' ' || *CIP == '\t')) | |||
103 | ++CIP; | |||
104 | ||||
105 | if (CIP < CPUInfoEnd) { | |||
106 | CPUStart = CIP; | |||
107 | while (CIP < CPUInfoEnd && (*CIP != ' ' && *CIP != '\t' && | |||
108 | *CIP != ',' && *CIP != '\n')) | |||
109 | ++CIP; | |||
110 | CPULen = CIP - CPUStart; | |||
111 | } | |||
112 | } | |||
113 | } | |||
114 | } | |||
115 | } | |||
116 | ||||
117 | if (CPUStart == 0) | |||
118 | while (CIP < CPUInfoEnd && *CIP != '\n') | |||
| ||||
119 | ++CIP; | |||
120 | } | |||
121 | ||||
122 | if (CPUStart == 0) | |||
123 | return generic; | |||
124 | ||||
125 | return StringSwitch<const char *>(StringRef(CPUStart, CPULen)) | |||
126 | .Case("604e", "604e") | |||
127 | .Case("604", "604") | |||
128 | .Case("7400", "7400") | |||
129 | .Case("7410", "7400") | |||
130 | .Case("7447", "7400") | |||
131 | .Case("7455", "7450") | |||
132 | .Case("G4", "g4") | |||
133 | .Case("POWER4", "970") | |||
134 | .Case("PPC970FX", "970") | |||
135 | .Case("PPC970MP", "970") | |||
136 | .Case("G5", "g5") | |||
137 | .Case("POWER5", "g5") | |||
138 | .Case("A2", "a2") | |||
139 | .Case("POWER6", "pwr6") | |||
140 | .Case("POWER7", "pwr7") | |||
141 | .Case("POWER8", "pwr8") | |||
142 | .Case("POWER8E", "pwr8") | |||
143 | .Case("POWER8NVL", "pwr8") | |||
144 | .Case("POWER9", "pwr9") | |||
145 | .Default(generic); | |||
146 | } | |||
147 | ||||
148 | StringRef sys::detail::getHostCPUNameForARM( | |||
149 | const StringRef &ProcCpuinfoContent) { | |||
150 | // The cpuid register on arm is not accessible from user space. On Linux, | |||
151 | // it is exposed through the /proc/cpuinfo file. | |||
152 | ||||
153 | // Read 32 lines from /proc/cpuinfo, which should contain the CPU part line | |||
154 | // in all cases. | |||
155 | SmallVector<StringRef, 32> Lines; | |||
156 | ProcCpuinfoContent.split(Lines, "\n"); | |||
157 | ||||
158 | // Look for the CPU implementer line. | |||
159 | StringRef Implementer; | |||
160 | StringRef Hardware; | |||
161 | for (unsigned I = 0, E = Lines.size(); I != E; ++I) { | |||
162 | if (Lines[I].startswith("CPU implementer")) | |||
163 | Implementer = Lines[I].substr(15).ltrim("\t :"); | |||
164 | if (Lines[I].startswith("Hardware")) | |||
165 | Hardware = Lines[I].substr(8).ltrim("\t :"); | |||
166 | } | |||
167 | ||||
168 | if (Implementer == "0x41") { // ARM Ltd. | |||
169 | // MSM8992/8994 may give cpu part for the core that the kernel is running on, | |||
170 | // which is undeterministic and wrong. Always return cortex-a53 for these SoC. | |||
171 | if (Hardware.endswith("MSM8994") || Hardware.endswith("MSM8996")) | |||
172 | return "cortex-a53"; | |||
173 | ||||
174 | ||||
175 | // Look for the CPU part line. | |||
176 | for (unsigned I = 0, E = Lines.size(); I != E; ++I) | |||
177 | if (Lines[I].startswith("CPU part")) | |||
178 | // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The | |||
179 | // values correspond to the "Part number" in the CP15/c0 register. The | |||
180 | // contents are specified in the various processor manuals. | |||
181 | return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) | |||
182 | .Case("0x926", "arm926ej-s") | |||
183 | .Case("0xb02", "mpcore") | |||
184 | .Case("0xb36", "arm1136j-s") | |||
185 | .Case("0xb56", "arm1156t2-s") | |||
186 | .Case("0xb76", "arm1176jz-s") | |||
187 | .Case("0xc08", "cortex-a8") | |||
188 | .Case("0xc09", "cortex-a9") | |||
189 | .Case("0xc0f", "cortex-a15") | |||
190 | .Case("0xc20", "cortex-m0") | |||
191 | .Case("0xc23", "cortex-m3") | |||
192 | .Case("0xc24", "cortex-m4") | |||
193 | .Case("0xd04", "cortex-a35") | |||
194 | .Case("0xd03", "cortex-a53") | |||
195 | .Case("0xd07", "cortex-a57") | |||
196 | .Case("0xd08", "cortex-a72") | |||
197 | .Case("0xd09", "cortex-a73") | |||
198 | .Default("generic"); | |||
199 | } | |||
200 | ||||
201 | if (Implementer == "0x51") // Qualcomm Technologies, Inc. | |||
202 | // Look for the CPU part line. | |||
203 | for (unsigned I = 0, E = Lines.size(); I != E; ++I) | |||
204 | if (Lines[I].startswith("CPU part")) | |||
205 | // The CPU part is a 3 digit hexadecimal number with a 0x prefix. The | |||
206 | // values correspond to the "Part number" in the CP15/c0 register. The | |||
207 | // contents are specified in the various processor manuals. | |||
208 | return StringSwitch<const char *>(Lines[I].substr(8).ltrim("\t :")) | |||
209 | .Case("0x06f", "krait") // APQ8064 | |||
210 | .Case("0x201", "kryo") | |||
211 | .Case("0x205", "kryo") | |||
212 | .Case("0x211", "kryo") | |||
213 | .Case("0x800", "cortex-a73") | |||
214 | .Case("0x801", "cortex-a73") | |||
215 | .Case("0xc00", "falkor") | |||
216 | .Case("0xc01", "saphira") | |||
217 | .Default("generic"); | |||
218 | ||||
219 | if (Implementer == "0x53") { // Samsung Electronics Co., Ltd. | |||
220 | // The Exynos chips have a convoluted ID scheme that doesn't seem to follow | |||
221 | // any predictive pattern across variants and parts. | |||
222 | unsigned Variant = 0, Part = 0; | |||
223 | ||||
224 | // Look for the CPU variant line, whose value is a 1 digit hexadecimal | |||
225 | // number, corresponding to the Variant bits in the CP15/C0 register. | |||
226 | for (auto I : Lines) | |||
227 | if (I.consume_front("CPU variant")) | |||
228 | I.ltrim("\t :").getAsInteger(0, Variant); | |||
229 | ||||
230 | // Look for the CPU part line, whose value is a 3 digit hexadecimal | |||
231 | // number, corresponding to the PartNum bits in the CP15/C0 register. | |||
232 | for (auto I : Lines) | |||
233 | if (I.consume_front("CPU part")) | |||
234 | I.ltrim("\t :").getAsInteger(0, Part); | |||
235 | ||||
236 | unsigned Exynos = (Variant << 12) | Part; | |||
237 | switch (Exynos) { | |||
238 | default: | |||
239 | // Default by falling through to Exynos M1. | |||
240 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
241 | ||||
242 | case 0x1001: | |||
243 | return "exynos-m1"; | |||
244 | ||||
245 | case 0x4001: | |||
246 | return "exynos-m2"; | |||
247 | } | |||
248 | } | |||
249 | ||||
250 | return "generic"; | |||
251 | } | |||
252 | ||||
253 | StringRef sys::detail::getHostCPUNameForS390x( | |||
254 | const StringRef &ProcCpuinfoContent) { | |||
255 | // STIDP is a privileged operation, so use /proc/cpuinfo instead. | |||
256 | ||||
257 | // The "processor 0:" line comes after a fair amount of other information, | |||
258 | // including a cache breakdown, but this should be plenty. | |||
259 | SmallVector<StringRef, 32> Lines; | |||
260 | ProcCpuinfoContent.split(Lines, "\n"); | |||
261 | ||||
262 | // Look for the CPU features. | |||
263 | SmallVector<StringRef, 32> CPUFeatures; | |||
264 | for (unsigned I = 0, E = Lines.size(); I != E; ++I) | |||
265 | if (Lines[I].startswith("features")) { | |||
266 | size_t Pos = Lines[I].find(":"); | |||
267 | if (Pos != StringRef::npos) { | |||
268 | Lines[I].drop_front(Pos + 1).split(CPUFeatures, ' '); | |||
269 | break; | |||
270 | } | |||
271 | } | |||
272 | ||||
273 | // We need to check for the presence of vector support independently of | |||
274 | // the machine type, since we may only use the vector register set when | |||
275 | // supported by the kernel (and hypervisor). | |||
276 | bool HaveVectorSupport = false; | |||
277 | for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { | |||
278 | if (CPUFeatures[I] == "vx") | |||
279 | HaveVectorSupport = true; | |||
280 | } | |||
281 | ||||
282 | // Now check the processor machine type. | |||
283 | for (unsigned I = 0, E = Lines.size(); I != E; ++I) { | |||
284 | if (Lines[I].startswith("processor ")) { | |||
285 | size_t Pos = Lines[I].find("machine = "); | |||
286 | if (Pos != StringRef::npos) { | |||
287 | Pos += sizeof("machine = ") - 1; | |||
288 | unsigned int Id; | |||
289 | if (!Lines[I].drop_front(Pos).getAsInteger(10, Id)) { | |||
290 | if (Id >= 3906 && HaveVectorSupport) | |||
291 | return "z14"; | |||
292 | if (Id >= 2964 && HaveVectorSupport) | |||
293 | return "z13"; | |||
294 | if (Id >= 2827) | |||
295 | return "zEC12"; | |||
296 | if (Id >= 2817) | |||
297 | return "z196"; | |||
298 | } | |||
299 | } | |||
300 | break; | |||
301 | } | |||
302 | } | |||
303 | ||||
304 | return "generic"; | |||
305 | } | |||
306 | ||||
307 | StringRef sys::detail::getHostCPUNameForBPF() { | |||
308 | #if !defined(__linux__1) || !defined(__x86_64__1) | |||
309 | return "generic"; | |||
310 | #else | |||
311 | uint8_t insns[40] __attribute__ ((aligned (8))) = | |||
312 | /* BPF_MOV64_IMM(BPF_REG_0, 0) */ | |||
313 | { 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, | |||
314 | /* BPF_MOV64_IMM(BPF_REG_2, 1) */ | |||
315 | 0xb7, 0x2, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, | |||
316 | /* BPF_JMP_REG(BPF_JLT, BPF_REG_0, BPF_REG_2, 1) */ | |||
317 | 0xad, 0x20, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, | |||
318 | /* BPF_MOV64_IMM(BPF_REG_0, 1) */ | |||
319 | 0xb7, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, | |||
320 | /* BPF_EXIT_INSN() */ | |||
321 | 0x95, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; | |||
322 | ||||
323 | struct bpf_prog_load_attr { | |||
324 | uint32_t prog_type; | |||
325 | uint32_t insn_cnt; | |||
326 | uint64_t insns; | |||
327 | uint64_t license; | |||
328 | uint32_t log_level; | |||
329 | uint32_t log_size; | |||
330 | uint64_t log_buf; | |||
331 | uint32_t kern_version; | |||
332 | uint32_t prog_flags; | |||
333 | } attr = {}; | |||
334 | attr.prog_type = 1; /* BPF_PROG_TYPE_SOCKET_FILTER */ | |||
335 | attr.insn_cnt = 5; | |||
336 | attr.insns = (uint64_t)insns; | |||
337 | attr.license = (uint64_t)"DUMMY"; | |||
338 | ||||
339 | int fd = syscall(321 /* __NR_bpf */, 5 /* BPF_PROG_LOAD */, &attr, sizeof(attr)); | |||
340 | if (fd >= 0) { | |||
341 | close(fd); | |||
342 | return "v2"; | |||
343 | } | |||
344 | return "v1"; | |||
345 | #endif | |||
346 | } | |||
347 | ||||
348 | #if defined(__i386__) || defined(_M_IX86) || \ | |||
349 | defined(__x86_64__1) || defined(_M_X64) | |||
350 | ||||
351 | enum VendorSignatures { | |||
352 | SIG_INTEL = 0x756e6547 /* Genu */, | |||
353 | SIG_AMD = 0x68747541 /* Auth */ | |||
354 | }; | |||
355 | ||||
356 | // The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max). | |||
357 | // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID | |||
358 | // support. Consequently, for i386, the presence of CPUID is checked first | |||
359 | // via the corresponding eflags bit. | |||
360 | // Removal of cpuid.h header motivated by PR30384 | |||
361 | // Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp | |||
362 | // or test-suite, but are used in external projects e.g. libstdcxx | |||
363 | static bool isCpuIdSupported() { | |||
364 | #if defined(__GNUC__4) || defined(__clang__1) | |||
365 | #if defined(__i386__) | |||
366 | int __cpuid_supported; | |||
367 | __asm__(" pushfl\n" | |||
368 | " popl %%eax\n" | |||
369 | " movl %%eax,%%ecx\n" | |||
370 | " xorl $0x00200000,%%eax\n" | |||
371 | " pushl %%eax\n" | |||
372 | " popfl\n" | |||
373 | " pushfl\n" | |||
374 | " popl %%eax\n" | |||
375 | " movl $0,%0\n" | |||
376 | " cmpl %%eax,%%ecx\n" | |||
377 | " je 1f\n" | |||
378 | " movl $1,%0\n" | |||
379 | "1:" | |||
380 | : "=r"(__cpuid_supported) | |||
381 | : | |||
382 | : "eax", "ecx"); | |||
383 | if (!__cpuid_supported) | |||
384 | return false; | |||
385 | #endif | |||
386 | return true; | |||
387 | #endif | |||
388 | return true; | |||
389 | } | |||
390 | ||||
391 | /// getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in | |||
392 | /// the specified arguments. If we can't run cpuid on the host, return true. | |||
393 | static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX, | |||
394 | unsigned *rECX, unsigned *rEDX) { | |||
395 | #if defined(__GNUC__4) || defined(__clang__1) | |||
396 | #if defined(__x86_64__1) | |||
397 | // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. | |||
398 | // FIXME: should we save this for Clang? | |||
399 | __asm__("movq\t%%rbx, %%rsi\n\t" | |||
400 | "cpuid\n\t" | |||
401 | "xchgq\t%%rbx, %%rsi\n\t" | |||
402 | : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) | |||
403 | : "a"(value)); | |||
404 | return false; | |||
405 | #elif defined(__i386__) | |||
406 | __asm__("movl\t%%ebx, %%esi\n\t" | |||
407 | "cpuid\n\t" | |||
408 | "xchgl\t%%ebx, %%esi\n\t" | |||
409 | : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) | |||
410 | : "a"(value)); | |||
411 | return false; | |||
412 | #else | |||
413 | return true; | |||
414 | #endif | |||
415 | #elif defined(_MSC_VER) | |||
416 | // The MSVC intrinsic is portable across x86 and x64. | |||
417 | int registers[4]; | |||
418 | __cpuid(registers, value); | |||
419 | *rEAX = registers[0]; | |||
420 | *rEBX = registers[1]; | |||
421 | *rECX = registers[2]; | |||
422 | *rEDX = registers[3]; | |||
423 | return false; | |||
424 | #else | |||
425 | return true; | |||
426 | #endif | |||
427 | } | |||
428 | ||||
429 | /// getX86CpuIDAndInfoEx - Execute the specified cpuid with subleaf and return | |||
430 | /// the 4 values in the specified arguments. If we can't run cpuid on the host, | |||
431 | /// return true. | |||
432 | static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf, | |||
433 | unsigned *rEAX, unsigned *rEBX, unsigned *rECX, | |||
434 | unsigned *rEDX) { | |||
435 | #if defined(__GNUC__4) || defined(__clang__1) | |||
436 | #if defined(__x86_64__1) | |||
437 | // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually. | |||
438 | // FIXME: should we save this for Clang? | |||
439 | __asm__("movq\t%%rbx, %%rsi\n\t" | |||
440 | "cpuid\n\t" | |||
441 | "xchgq\t%%rbx, %%rsi\n\t" | |||
442 | : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) | |||
443 | : "a"(value), "c"(subleaf)); | |||
444 | return false; | |||
445 | #elif defined(__i386__) | |||
446 | __asm__("movl\t%%ebx, %%esi\n\t" | |||
447 | "cpuid\n\t" | |||
448 | "xchgl\t%%ebx, %%esi\n\t" | |||
449 | : "=a"(*rEAX), "=S"(*rEBX), "=c"(*rECX), "=d"(*rEDX) | |||
450 | : "a"(value), "c"(subleaf)); | |||
451 | return false; | |||
452 | #else | |||
453 | return true; | |||
454 | #endif | |||
455 | #elif defined(_MSC_VER) | |||
456 | int registers[4]; | |||
457 | __cpuidex(registers, value, subleaf); | |||
458 | *rEAX = registers[0]; | |||
459 | *rEBX = registers[1]; | |||
460 | *rECX = registers[2]; | |||
461 | *rEDX = registers[3]; | |||
462 | return false; | |||
463 | #else | |||
464 | return true; | |||
465 | #endif | |||
466 | } | |||
467 | ||||
468 | // Read control register 0 (XCR0). Used to detect features such as AVX. | |||
469 | static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) { | |||
470 | #if defined(__GNUC__4) || defined(__clang__1) | |||
471 | // Check xgetbv; this uses a .byte sequence instead of the instruction | |||
472 | // directly because older assemblers do not include support for xgetbv and | |||
473 | // there is no easy way to conditionally compile based on the assembler used. | |||
474 | __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(*rEAX), "=d"(*rEDX) : "c"(0)); | |||
475 | return false; | |||
476 | #elif defined(_MSC_FULL_VER) && defined(_XCR_XFEATURE_ENABLED_MASK) | |||
477 | unsigned long long Result = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); | |||
478 | *rEAX = Result; | |||
479 | *rEDX = Result >> 32; | |||
480 | return false; | |||
481 | #else | |||
482 | return true; | |||
483 | #endif | |||
484 | } | |||
485 | ||||
486 | static void detectX86FamilyModel(unsigned EAX, unsigned *Family, | |||
487 | unsigned *Model) { | |||
488 | *Family = (EAX >> 8) & 0xf; // Bits 8 - 11 | |||
489 | *Model = (EAX >> 4) & 0xf; // Bits 4 - 7 | |||
490 | if (*Family == 6 || *Family == 0xf) { | |||
491 | if (*Family == 0xf) | |||
492 | // Examine extended family ID if family ID is F. | |||
493 | *Family += (EAX >> 20) & 0xff; // Bits 20 - 27 | |||
494 | // Examine extended model ID if family ID is 6 or F. | |||
495 | *Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19 | |||
496 | } | |||
497 | } | |||
498 | ||||
499 | static void | |||
500 | getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, | |||
501 | unsigned Brand_id, unsigned Features, | |||
502 | unsigned Features2, unsigned *Type, | |||
503 | unsigned *Subtype) { | |||
504 | if (Brand_id != 0) | |||
505 | return; | |||
506 | switch (Family) { | |||
507 | case 3: | |||
508 | *Type = X86::INTEL_i386; | |||
509 | break; | |||
510 | case 4: | |||
511 | *Type = X86::INTEL_i486; | |||
512 | break; | |||
513 | case 5: | |||
514 | if (Features & (1 << X86::FEATURE_MMX)) { | |||
515 | *Type = X86::INTEL_PENTIUM_MMX; | |||
516 | break; | |||
517 | } | |||
518 | *Type = X86::INTEL_PENTIUM; | |||
519 | break; | |||
520 | case 6: | |||
521 | switch (Model) { | |||
522 | case 0x01: // Pentium Pro processor | |||
523 | *Type = X86::INTEL_PENTIUM_PRO; | |||
524 | break; | |||
525 | case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor, | |||
526 | // model 03 | |||
527 | case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor, | |||
528 | // model 05, and Intel Celeron processor, model 05 | |||
529 | case 0x06: // Celeron processor, model 06 | |||
530 | *Type = X86::INTEL_PENTIUM_II; | |||
531 | break; | |||
532 | case 0x07: // Pentium III processor, model 07, and Pentium III Xeon | |||
533 | // processor, model 07 | |||
534 | case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor, | |||
535 | // model 08, and Celeron processor, model 08 | |||
536 | case 0x0a: // Pentium III Xeon processor, model 0Ah | |||
537 | case 0x0b: // Pentium III processor, model 0Bh | |||
538 | *Type = X86::INTEL_PENTIUM_III; | |||
539 | break; | |||
540 | case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09. | |||
541 | case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model | |||
542 | // 0Dh. All processors are manufactured using the 90 nm process. | |||
543 | case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579 | |||
544 | // Integrated Processor with Intel QuickAssist Technology | |||
545 | *Type = X86::INTEL_PENTIUM_M; | |||
546 | break; | |||
547 | case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model | |||
548 | // 0Eh. All processors are manufactured using the 65 nm process. | |||
549 | *Type = X86::INTEL_CORE_DUO; | |||
550 | break; // yonah | |||
551 | case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile | |||
552 | // processor, Intel Core 2 Quad processor, Intel Core 2 Quad | |||
553 | // mobile processor, Intel Core 2 Extreme processor, Intel | |||
554 | // Pentium Dual-Core processor, Intel Xeon processor, model | |||
555 | // 0Fh. All processors are manufactured using the 65 nm process. | |||
556 | case 0x16: // Intel Celeron processor model 16h. All processors are | |||
557 | // manufactured using the 65 nm process | |||
558 | *Type = X86::INTEL_CORE2; // "core2" | |||
559 | *Subtype = X86::INTEL_CORE2_65; | |||
560 | break; | |||
561 | case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model | |||
562 | // 17h. All processors are manufactured using the 45 nm process. | |||
563 | // | |||
564 | // 45nm: Penryn , Wolfdale, Yorkfield (XE) | |||
565 | case 0x1d: // Intel Xeon processor MP. All processors are manufactured using | |||
566 | // the 45 nm process. | |||
567 | *Type = X86::INTEL_CORE2; // "penryn" | |||
568 | *Subtype = X86::INTEL_CORE2_45; | |||
569 | break; | |||
570 | case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All | |||
571 | // processors are manufactured using the 45 nm process. | |||
572 | case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. | |||
573 | // As found in a Summer 2010 model iMac. | |||
574 | case 0x1f: | |||
575 | case 0x2e: // Nehalem EX | |||
576 | *Type = X86::INTEL_COREI7; // "nehalem" | |||
577 | *Subtype = X86::INTEL_COREI7_NEHALEM; | |||
578 | break; | |||
579 | case 0x25: // Intel Core i7, laptop version. | |||
580 | case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All | |||
581 | // processors are manufactured using the 32 nm process. | |||
582 | case 0x2f: // Westmere EX | |||
583 | *Type = X86::INTEL_COREI7; // "westmere" | |||
584 | *Subtype = X86::INTEL_COREI7_WESTMERE; | |||
585 | break; | |||
586 | case 0x2a: // Intel Core i7 processor. All processors are manufactured | |||
587 | // using the 32 nm process. | |||
588 | case 0x2d: | |||
589 | *Type = X86::INTEL_COREI7; //"sandybridge" | |||
590 | *Subtype = X86::INTEL_COREI7_SANDYBRIDGE; | |||
591 | break; | |||
592 | case 0x3a: | |||
593 | case 0x3e: // Ivy Bridge EP | |||
594 | *Type = X86::INTEL_COREI7; // "ivybridge" | |||
595 | *Subtype = X86::INTEL_COREI7_IVYBRIDGE; | |||
596 | break; | |||
597 | ||||
598 | // Haswell: | |||
599 | case 0x3c: | |||
600 | case 0x3f: | |||
601 | case 0x45: | |||
602 | case 0x46: | |||
603 | *Type = X86::INTEL_COREI7; // "haswell" | |||
604 | *Subtype = X86::INTEL_COREI7_HASWELL; | |||
605 | break; | |||
606 | ||||
607 | // Broadwell: | |||
608 | case 0x3d: | |||
609 | case 0x47: | |||
610 | case 0x4f: | |||
611 | case 0x56: | |||
612 | *Type = X86::INTEL_COREI7; // "broadwell" | |||
613 | *Subtype = X86::INTEL_COREI7_BROADWELL; | |||
614 | break; | |||
615 | ||||
616 | // Skylake: | |||
617 | case 0x4e: // Skylake mobile | |||
618 | case 0x5e: // Skylake desktop | |||
619 | case 0x8e: // Kaby Lake mobile | |||
620 | case 0x9e: // Kaby Lake desktop | |||
621 | *Type = X86::INTEL_COREI7; // "skylake" | |||
622 | *Subtype = X86::INTEL_COREI7_SKYLAKE; | |||
623 | break; | |||
624 | ||||
625 | // Skylake Xeon: | |||
626 | case 0x55: | |||
627 | *Type = X86::INTEL_COREI7; | |||
628 | *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512" | |||
629 | break; | |||
630 | ||||
631 | // Cannonlake: | |||
632 | case 0x66: | |||
633 | *Type = X86::INTEL_COREI7; | |||
634 | *Subtype = X86::INTEL_COREI7_CANNONLAKE; // "cannonlake" | |||
635 | break; | |||
636 | ||||
637 | case 0x1c: // Most 45 nm Intel Atom processors | |||
638 | case 0x26: // 45 nm Atom Lincroft | |||
639 | case 0x27: // 32 nm Atom Medfield | |||
640 | case 0x35: // 32 nm Atom Midview | |||
641 | case 0x36: // 32 nm Atom Midview | |||
642 | *Type = X86::INTEL_BONNELL; | |||
643 | break; // "bonnell" | |||
644 | ||||
645 | // Atom Silvermont codes from the Intel software optimization guide. | |||
646 | case 0x37: | |||
647 | case 0x4a: | |||
648 | case 0x4d: | |||
649 | case 0x5a: | |||
650 | case 0x5d: | |||
651 | case 0x4c: // really airmont | |||
652 | *Type = X86::INTEL_SILVERMONT; | |||
653 | break; // "silvermont" | |||
654 | // Goldmont: | |||
655 | case 0x5c: // Apollo Lake | |||
656 | case 0x5f: // Denverton | |||
657 | case 0x7a: // Gemini Lake | |||
658 | *Type = X86::INTEL_GOLDMONT; | |||
659 | break; // "goldmont" | |||
660 | case 0x57: | |||
661 | *Type = X86::INTEL_KNL; // knl | |||
662 | break; | |||
663 | case 0x85: | |||
664 | *Type = X86::INTEL_KNM; // knm | |||
665 | break; | |||
666 | ||||
667 | default: // Unknown family 6 CPU, try to guess. | |||
668 | if (Features & (1 << X86::FEATURE_AVX512VBMI)) { | |||
669 | *Type = X86::INTEL_COREI7; | |||
670 | *Subtype = X86::INTEL_COREI7_CANNONLAKE; | |||
671 | break; | |||
672 | } | |||
673 | ||||
674 | if (Features & (1 << X86::FEATURE_AVX512VL)) { | |||
675 | *Type = X86::INTEL_COREI7; | |||
676 | *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; | |||
677 | break; | |||
678 | } | |||
679 | ||||
680 | if (Features & (1 << X86::FEATURE_AVX512ER)) { | |||
681 | *Type = X86::INTEL_KNL; // knl | |||
682 | break; | |||
683 | } | |||
684 | ||||
685 | if (Features2 & (1 << (X86::FEATURE_CLFLUSHOPT - 32))) { | |||
686 | if (Features2 & (1 << (X86::FEATURE_SHA - 32))) { | |||
687 | *Type = X86::INTEL_GOLDMONT; | |||
688 | } else { | |||
689 | *Type = X86::INTEL_COREI7; | |||
690 | *Subtype = X86::INTEL_COREI7_SKYLAKE; | |||
691 | } | |||
692 | break; | |||
693 | } | |||
694 | if (Features2 & (1 << (X86::FEATURE_ADX - 32))) { | |||
695 | *Type = X86::INTEL_COREI7; | |||
696 | *Subtype = X86::INTEL_COREI7_BROADWELL; | |||
697 | break; | |||
698 | } | |||
699 | if (Features & (1 << X86::FEATURE_AVX2)) { | |||
700 | *Type = X86::INTEL_COREI7; | |||
701 | *Subtype = X86::INTEL_COREI7_HASWELL; | |||
702 | break; | |||
703 | } | |||
704 | if (Features & (1 << X86::FEATURE_AVX)) { | |||
705 | *Type = X86::INTEL_COREI7; | |||
706 | *Subtype = X86::INTEL_COREI7_SANDYBRIDGE; | |||
707 | break; | |||
708 | } | |||
709 | if (Features & (1 << X86::FEATURE_SSE4_2)) { | |||
710 | if (Features2 & (1 << (X86::FEATURE_MOVBE - 32))) { | |||
711 | *Type = X86::INTEL_SILVERMONT; | |||
712 | } else { | |||
713 | *Type = X86::INTEL_COREI7; | |||
714 | *Subtype = X86::INTEL_COREI7_NEHALEM; | |||
715 | } | |||
716 | break; | |||
717 | } | |||
718 | if (Features & (1 << X86::FEATURE_SSE4_1)) { | |||
719 | *Type = X86::INTEL_CORE2; // "penryn" | |||
720 | *Subtype = X86::INTEL_CORE2_45; | |||
721 | break; | |||
722 | } | |||
723 | if (Features & (1 << X86::FEATURE_SSSE3)) { | |||
724 | if (Features2 & (1 << (X86::FEATURE_MOVBE - 32))) { | |||
725 | *Type = X86::INTEL_BONNELL; // "bonnell" | |||
726 | } else { | |||
727 | *Type = X86::INTEL_CORE2; // "core2" | |||
728 | *Subtype = X86::INTEL_CORE2_65; | |||
729 | } | |||
730 | break; | |||
731 | } | |||
732 | if (Features2 & (1 << (X86::FEATURE_EM64T - 32))) { | |||
733 | *Type = X86::INTEL_CORE2; // "core2" | |||
734 | *Subtype = X86::INTEL_CORE2_65; | |||
735 | break; | |||
736 | } | |||
737 | if (Features & (1 << X86::FEATURE_SSE3)) { | |||
738 | *Type = X86::INTEL_CORE_DUO; | |||
739 | break; | |||
740 | } | |||
741 | if (Features & (1 << X86::FEATURE_SSE2)) { | |||
742 | *Type = X86::INTEL_PENTIUM_M; | |||
743 | break; | |||
744 | } | |||
745 | if (Features & (1 << X86::FEATURE_SSE)) { | |||
746 | *Type = X86::INTEL_PENTIUM_III; | |||
747 | break; | |||
748 | } | |||
749 | if (Features & (1 << X86::FEATURE_MMX)) { | |||
750 | *Type = X86::INTEL_PENTIUM_II; | |||
751 | break; | |||
752 | } | |||
753 | *Type = X86::INTEL_PENTIUM_PRO; | |||
754 | break; | |||
755 | } | |||
756 | break; | |||
757 | case 15: { | |||
758 | if (Features2 & (1 << (X86::FEATURE_EM64T - 32))) { | |||
759 | *Type = X86::INTEL_NOCONA; | |||
760 | break; | |||
761 | } | |||
762 | if (Features & (1 << X86::FEATURE_SSE3)) { | |||
763 | *Type = X86::INTEL_PRESCOTT; | |||
764 | break; | |||
765 | } | |||
766 | *Type = X86::INTEL_PENTIUM_IV; | |||
767 | break; | |||
768 | } | |||
769 | default: | |||
770 | break; /*"generic"*/ | |||
771 | } | |||
772 | } | |||
773 | ||||
774 | static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model, | |||
775 | unsigned Features, unsigned *Type, | |||
776 | unsigned *Subtype) { | |||
777 | // FIXME: this poorly matches the generated SubtargetFeatureKV table. There | |||
778 | // appears to be no way to generate the wide variety of AMD-specific targets | |||
779 | // from the information returned from CPUID. | |||
780 | switch (Family) { | |||
781 | case 4: | |||
782 | *Type = X86::AMD_i486; | |||
783 | break; | |||
784 | case 5: | |||
785 | *Type = X86::AMDPENTIUM; | |||
786 | switch (Model) { | |||
787 | case 6: | |||
788 | case 7: | |||
789 | *Subtype = X86::AMDPENTIUM_K6; | |||
790 | break; // "k6" | |||
791 | case 8: | |||
792 | *Subtype = X86::AMDPENTIUM_K62; | |||
793 | break; // "k6-2" | |||
794 | case 9: | |||
795 | case 13: | |||
796 | *Subtype = X86::AMDPENTIUM_K63; | |||
797 | break; // "k6-3" | |||
798 | case 10: | |||
799 | *Subtype = X86::AMDPENTIUM_GEODE; | |||
800 | break; // "geode" | |||
801 | } | |||
802 | break; | |||
803 | case 6: | |||
804 | if (Features & (1 << X86::FEATURE_SSE)) { | |||
805 | *Type = X86::AMD_ATHLON_XP; | |||
806 | break; // "athlon-xp" | |||
807 | } | |||
808 | *Type = X86::AMD_ATHLON; | |||
809 | break; // "athlon" | |||
810 | case 15: | |||
811 | if (Features & (1 << X86::FEATURE_SSE3)) { | |||
812 | *Type = X86::AMD_K8SSE3; | |||
813 | break; // "k8-sse3" | |||
814 | } | |||
815 | *Type = X86::AMD_K8; | |||
816 | break; // "k8" | |||
817 | case 16: | |||
818 | *Type = X86::AMDFAM10H; // "amdfam10" | |||
819 | switch (Model) { | |||
820 | case 2: | |||
821 | *Subtype = X86::AMDFAM10H_BARCELONA; | |||
822 | break; | |||
823 | case 4: | |||
824 | *Subtype = X86::AMDFAM10H_SHANGHAI; | |||
825 | break; | |||
826 | case 8: | |||
827 | *Subtype = X86::AMDFAM10H_ISTANBUL; | |||
828 | break; | |||
829 | } | |||
830 | break; | |||
831 | case 20: | |||
832 | *Type = X86::AMD_BTVER1; | |||
833 | break; // "btver1"; | |||
834 | case 21: | |||
835 | *Type = X86::AMDFAM15H; | |||
836 | if (Model >= 0x60 && Model <= 0x7f) { | |||
837 | *Subtype = X86::AMDFAM15H_BDVER4; | |||
838 | break; // "bdver4"; 60h-7Fh: Excavator | |||
839 | } | |||
840 | if (Model >= 0x30 && Model <= 0x3f) { | |||
841 | *Subtype = X86::AMDFAM15H_BDVER3; | |||
842 | break; // "bdver3"; 30h-3Fh: Steamroller | |||
843 | } | |||
844 | if (Model >= 0x10 && Model <= 0x1f) { | |||
845 | *Subtype = X86::AMDFAM15H_BDVER2; | |||
846 | break; // "bdver2"; 10h-1Fh: Piledriver | |||
847 | } | |||
848 | if (Model <= 0x0f) { | |||
849 | *Subtype = X86::AMDFAM15H_BDVER1; | |||
850 | break; // "bdver1"; 00h-0Fh: Bulldozer | |||
851 | } | |||
852 | break; | |||
853 | case 22: | |||
854 | *Type = X86::AMD_BTVER2; | |||
855 | break; // "btver2" | |||
856 | case 23: | |||
857 | *Type = X86::AMDFAM17H; | |||
858 | *Subtype = X86::AMDFAM17H_ZNVER1; | |||
859 | break; | |||
860 | default: | |||
861 | break; // "generic" | |||
862 | } | |||
863 | } | |||
864 | ||||
865 | static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf, | |||
866 | unsigned *FeaturesOut, | |||
867 | unsigned *Features2Out) { | |||
868 | unsigned Features = 0; | |||
869 | unsigned Features2 = 0; | |||
870 | unsigned EAX, EBX; | |||
871 | ||||
872 | if ((EDX >> 15) & 1) | |||
873 | Features |= 1 << X86::FEATURE_CMOV; | |||
874 | if ((EDX >> 23) & 1) | |||
875 | Features |= 1 << X86::FEATURE_MMX; | |||
876 | if ((EDX >> 25) & 1) | |||
877 | Features |= 1 << X86::FEATURE_SSE; | |||
878 | if ((EDX >> 26) & 1) | |||
879 | Features |= 1 << X86::FEATURE_SSE2; | |||
880 | ||||
881 | if ((ECX >> 0) & 1) | |||
882 | Features |= 1 << X86::FEATURE_SSE3; | |||
883 | if ((ECX >> 1) & 1) | |||
884 | Features |= 1 << X86::FEATURE_PCLMUL; | |||
885 | if ((ECX >> 9) & 1) | |||
886 | Features |= 1 << X86::FEATURE_SSSE3; | |||
887 | if ((ECX >> 12) & 1) | |||
888 | Features |= 1 << X86::FEATURE_FMA; | |||
889 | if ((ECX >> 19) & 1) | |||
890 | Features |= 1 << X86::FEATURE_SSE4_1; | |||
891 | if ((ECX >> 20) & 1) | |||
892 | Features |= 1 << X86::FEATURE_SSE4_2; | |||
893 | if ((ECX >> 23) & 1) | |||
894 | Features |= 1 << X86::FEATURE_POPCNT; | |||
895 | if ((ECX >> 25) & 1) | |||
896 | Features |= 1 << X86::FEATURE_AES; | |||
897 | ||||
898 | if ((ECX >> 22) & 1) | |||
899 | Features2 |= 1 << (X86::FEATURE_MOVBE - 32); | |||
900 | ||||
901 | // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV | |||
902 | // indicates that the AVX registers will be saved and restored on context | |||
903 | // switch, then we have full AVX support. | |||
904 | const unsigned AVXBits = (1 << 27) | (1 << 28); | |||
905 | bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) && | |||
906 | ((EAX & 0x6) == 0x6); | |||
907 | bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0); | |||
908 | ||||
909 | if (HasAVX) | |||
910 | Features |= 1 << X86::FEATURE_AVX; | |||
911 | ||||
912 | bool HasLeaf7 = | |||
913 | MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); | |||
914 | ||||
915 | if (HasLeaf7 && ((EBX >> 3) & 1)) | |||
916 | Features |= 1 << X86::FEATURE_BMI; | |||
917 | if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX) | |||
918 | Features |= 1 << X86::FEATURE_AVX2; | |||
919 | if (HasLeaf7 && ((EBX >> 9) & 1)) | |||
920 | Features |= 1 << X86::FEATURE_BMI2; | |||
921 | if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save) | |||
922 | Features |= 1 << X86::FEATURE_AVX512F; | |||
923 | if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save) | |||
924 | Features |= 1 << X86::FEATURE_AVX512DQ; | |||
925 | if (HasLeaf7 && ((EBX >> 19) & 1)) | |||
926 | Features2 |= 1 << (X86::FEATURE_ADX - 32); | |||
927 | if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save) | |||
928 | Features |= 1 << X86::FEATURE_AVX512IFMA; | |||
929 | if (HasLeaf7 && ((EBX >> 23) & 1)) | |||
930 | Features2 |= 1 << (X86::FEATURE_CLFLUSHOPT - 32); | |||
931 | if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save) | |||
932 | Features |= 1 << X86::FEATURE_AVX512PF; | |||
933 | if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save) | |||
934 | Features |= 1 << X86::FEATURE_AVX512ER; | |||
935 | if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save) | |||
936 | Features |= 1 << X86::FEATURE_AVX512CD; | |||
937 | if (HasLeaf7 && ((EBX >> 29) & 1)) | |||
938 | Features2 |= 1 << (X86::FEATURE_SHA - 32); | |||
939 | if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save) | |||
940 | Features |= 1 << X86::FEATURE_AVX512BW; | |||
941 | if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save) | |||
942 | Features |= 1 << X86::FEATURE_AVX512VL; | |||
943 | ||||
944 | if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save) | |||
945 | Features |= 1 << X86::FEATURE_AVX512VBMI; | |||
946 | if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save) | |||
947 | Features |= 1 << X86::FEATURE_AVX512VPOPCNTDQ; | |||
948 | ||||
949 | if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save) | |||
950 | Features |= 1 << X86::FEATURE_AVX5124VNNIW; | |||
951 | if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save) | |||
952 | Features |= 1 << X86::FEATURE_AVX5124FMAPS; | |||
953 | ||||
954 | unsigned MaxExtLevel; | |||
955 | getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX); | |||
956 | ||||
957 | bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 && | |||
958 | !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); | |||
959 | if (HasExtLeaf1 && ((ECX >> 6) & 1)) | |||
960 | Features |= 1 << X86::FEATURE_SSE4_A; | |||
961 | if (HasExtLeaf1 && ((ECX >> 11) & 1)) | |||
962 | Features |= 1 << X86::FEATURE_XOP; | |||
963 | if (HasExtLeaf1 && ((ECX >> 16) & 1)) | |||
964 | Features |= 1 << X86::FEATURE_FMA4; | |||
965 | ||||
966 | if (HasExtLeaf1 && ((EDX >> 29) & 1)) | |||
967 | Features2 |= 1 << (X86::FEATURE_EM64T - 32); | |||
968 | ||||
969 | *FeaturesOut = Features; | |||
970 | *Features2Out = Features2; | |||
971 | } | |||
972 | ||||
973 | StringRef sys::getHostCPUName() { | |||
974 | unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; | |||
975 | unsigned MaxLeaf, Vendor; | |||
976 | ||||
977 | #if defined(__GNUC__4) || defined(__clang__1) | |||
978 | //FIXME: include cpuid.h from clang or copy __get_cpuid_max here | |||
979 | // and simplify it to not invoke __cpuid (like cpu_model.c in | |||
980 | // compiler-rt/lib/builtins/cpu_model.c? | |||
981 | // Opting for the second option. | |||
982 | if(!isCpuIdSupported()) | |||
983 | return "generic"; | |||
984 | #endif | |||
985 | if (getX86CpuIDAndInfo(0, &MaxLeaf, &Vendor, &ECX, &EDX) || MaxLeaf < 1) | |||
986 | return "generic"; | |||
987 | getX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX); | |||
988 | ||||
989 | unsigned Brand_id = EBX & 0xff; | |||
990 | unsigned Family = 0, Model = 0; | |||
991 | unsigned Features = 0, Features2 = 0; | |||
992 | detectX86FamilyModel(EAX, &Family, &Model); | |||
993 | getAvailableFeatures(ECX, EDX, MaxLeaf, &Features, &Features2); | |||
994 | ||||
995 | unsigned Type = 0; | |||
996 | unsigned Subtype = 0; | |||
997 | ||||
998 | if (Vendor == SIG_INTEL) { | |||
999 | getIntelProcessorTypeAndSubtype(Family, Model, Brand_id, Features, | |||
1000 | Features2, &Type, &Subtype); | |||
1001 | } else if (Vendor == SIG_AMD) { | |||
1002 | getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype); | |||
1003 | } | |||
1004 | ||||
1005 | // Check subtypes first since those are more specific. | |||
1006 | #define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \ | |||
1007 | if (Subtype == X86::ENUM) \ | |||
1008 | return ARCHNAME; | |||
1009 | #include "llvm/Support/X86TargetParser.def" | |||
1010 | ||||
1011 | // Now check types. | |||
1012 | #define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \ | |||
1013 | if (Type == X86::ENUM) \ | |||
1014 | return ARCHNAME; | |||
1015 | #include "llvm/Support/X86TargetParser.def" | |||
1016 | ||||
1017 | return "generic"; | |||
1018 | } | |||
1019 | ||||
1020 | #elif defined(__APPLE__) && (defined(__ppc__) || defined(__powerpc__)) | |||
1021 | StringRef sys::getHostCPUName() { | |||
1022 | host_basic_info_data_t hostInfo; | |||
1023 | mach_msg_type_number_t infoCount; | |||
1024 | ||||
1025 | infoCount = HOST_BASIC_INFO_COUNT; | |||
1026 | host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, | |||
1027 | &infoCount); | |||
1028 | ||||
1029 | if (hostInfo.cpu_type != CPU_TYPE_POWERPC) | |||
1030 | return "generic"; | |||
1031 | ||||
1032 | switch (hostInfo.cpu_subtype) { | |||
1033 | case CPU_SUBTYPE_POWERPC_601: | |||
1034 | return "601"; | |||
1035 | case CPU_SUBTYPE_POWERPC_602: | |||
1036 | return "602"; | |||
1037 | case CPU_SUBTYPE_POWERPC_603: | |||
1038 | return "603"; | |||
1039 | case CPU_SUBTYPE_POWERPC_603e: | |||
1040 | return "603e"; | |||
1041 | case CPU_SUBTYPE_POWERPC_603ev: | |||
1042 | return "603ev"; | |||
1043 | case CPU_SUBTYPE_POWERPC_604: | |||
1044 | return "604"; | |||
1045 | case CPU_SUBTYPE_POWERPC_604e: | |||
1046 | return "604e"; | |||
1047 | case CPU_SUBTYPE_POWERPC_620: | |||
1048 | return "620"; | |||
1049 | case CPU_SUBTYPE_POWERPC_750: | |||
1050 | return "750"; | |||
1051 | case CPU_SUBTYPE_POWERPC_7400: | |||
1052 | return "7400"; | |||
1053 | case CPU_SUBTYPE_POWERPC_7450: | |||
1054 | return "7450"; | |||
1055 | case CPU_SUBTYPE_POWERPC_970: | |||
1056 | return "970"; | |||
1057 | default:; | |||
1058 | } | |||
1059 | ||||
1060 | return "generic"; | |||
1061 | } | |||
1062 | #elif defined(__linux__1) && (defined(__ppc__) || defined(__powerpc__)) | |||
1063 | StringRef sys::getHostCPUName() { | |||
1064 | std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); | |||
1065 | const StringRef& Content = P ? P->getBuffer() : ""; | |||
1066 | return detail::getHostCPUNameForPowerPC(Content); | |||
1067 | } | |||
1068 | #elif defined(__linux__1) && (defined(__arm__) || defined(__aarch64__)) | |||
1069 | StringRef sys::getHostCPUName() { | |||
1070 | std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); | |||
1071 | const StringRef& Content = P ? P->getBuffer() : ""; | |||
1072 | return detail::getHostCPUNameForARM(Content); | |||
1073 | } | |||
1074 | #elif defined(__linux__1) && defined(__s390x__) | |||
1075 | StringRef sys::getHostCPUName() { | |||
1076 | std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); | |||
1077 | const StringRef& Content = P ? P->getBuffer() : ""; | |||
1078 | return detail::getHostCPUNameForS390x(Content); | |||
1079 | } | |||
1080 | #else | |||
1081 | StringRef sys::getHostCPUName() { return "generic"; } | |||
1082 | #endif | |||
1083 | ||||
1084 | #if defined(__linux__1) && defined(__x86_64__1) | |||
1085 | // On Linux, the number of physical cores can be computed from /proc/cpuinfo, | |||
1086 | // using the number of unique physical/core id pairs. The following | |||
1087 | // implementation reads the /proc/cpuinfo format on an x86_64 system. | |||
1088 | static int computeHostNumPhysicalCores() { | |||
1089 | // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be | |||
1090 | // mmapped because it appears to have 0 size. | |||
1091 | llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text = | |||
1092 | llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo"); | |||
1093 | if (std::error_code EC = Text.getError()) { | |||
1094 | llvm::errs() << "Can't read " | |||
1095 | << "/proc/cpuinfo: " << EC.message() << "\n"; | |||
1096 | return -1; | |||
1097 | } | |||
1098 | SmallVector<StringRef, 8> strs; | |||
1099 | (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, | |||
1100 | /*KeepEmpty=*/false); | |||
1101 | int CurPhysicalId = -1; | |||
1102 | int CurCoreId = -1; | |||
1103 | SmallSet<std::pair<int, int>, 32> UniqueItems; | |||
1104 | for (auto &Line : strs) { | |||
1105 | Line = Line.trim(); | |||
1106 | if (!Line.startswith("physical id") && !Line.startswith("core id")) | |||
1107 | continue; | |||
1108 | std::pair<StringRef, StringRef> Data = Line.split(':'); | |||
1109 | auto Name = Data.first.trim(); | |||
1110 | auto Val = Data.second.trim(); | |||
1111 | if (Name == "physical id") { | |||
1112 | assert(CurPhysicalId == -1 &&(static_cast <bool> (CurPhysicalId == -1 && "Expected a core id before seeing another physical id" ) ? void (0) : __assert_fail ("CurPhysicalId == -1 && \"Expected a core id before seeing another physical id\"" , "/build/llvm-toolchain-snapshot-7~svn326551/lib/Support/Host.cpp" , 1113, __extension__ __PRETTY_FUNCTION__)) | |||
1113 | "Expected a core id before seeing another physical id")(static_cast <bool> (CurPhysicalId == -1 && "Expected a core id before seeing another physical id" ) ? void (0) : __assert_fail ("CurPhysicalId == -1 && \"Expected a core id before seeing another physical id\"" , "/build/llvm-toolchain-snapshot-7~svn326551/lib/Support/Host.cpp" , 1113, __extension__ __PRETTY_FUNCTION__)); | |||
1114 | Val.getAsInteger(10, CurPhysicalId); | |||
1115 | } | |||
1116 | if (Name == "core id") { | |||
1117 | assert(CurCoreId == -1 &&(static_cast <bool> (CurCoreId == -1 && "Expected a physical id before seeing another core id" ) ? void (0) : __assert_fail ("CurCoreId == -1 && \"Expected a physical id before seeing another core id\"" , "/build/llvm-toolchain-snapshot-7~svn326551/lib/Support/Host.cpp" , 1118, __extension__ __PRETTY_FUNCTION__)) | |||
1118 | "Expected a physical id before seeing another core id")(static_cast <bool> (CurCoreId == -1 && "Expected a physical id before seeing another core id" ) ? void (0) : __assert_fail ("CurCoreId == -1 && \"Expected a physical id before seeing another core id\"" , "/build/llvm-toolchain-snapshot-7~svn326551/lib/Support/Host.cpp" , 1118, __extension__ __PRETTY_FUNCTION__)); | |||
1119 | Val.getAsInteger(10, CurCoreId); | |||
1120 | } | |||
1121 | if (CurPhysicalId != -1 && CurCoreId != -1) { | |||
1122 | UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId)); | |||
1123 | CurPhysicalId = -1; | |||
1124 | CurCoreId = -1; | |||
1125 | } | |||
1126 | } | |||
1127 | return UniqueItems.size(); | |||
1128 | } | |||
1129 | #elif defined(__APPLE__) && defined(__x86_64__1) | |||
1130 | #include <sys/param.h> | |||
1131 | #include <sys/sysctl.h> | |||
1132 | ||||
1133 | // Gets the number of *physical cores* on the machine. | |||
1134 | static int computeHostNumPhysicalCores() { | |||
1135 | uint32_t count; | |||
1136 | size_t len = sizeof(count); | |||
1137 | sysctlbyname("hw.physicalcpu", &count, &len, NULL__null, 0); | |||
1138 | if (count < 1) { | |||
1139 | int nm[2]; | |||
1140 | nm[0] = CTL_HW; | |||
1141 | nm[1] = HW_AVAILCPU; | |||
1142 | sysctl(nm, 2, &count, &len, NULL__null, 0); | |||
1143 | if (count < 1) | |||
1144 | return -1; | |||
1145 | } | |||
1146 | return count; | |||
1147 | } | |||
1148 | #else | |||
1149 | // On other systems, return -1 to indicate unknown. | |||
1150 | static int computeHostNumPhysicalCores() { return -1; } | |||
1151 | #endif | |||
1152 | ||||
1153 | int sys::getHostNumPhysicalCores() { | |||
1154 | static int NumCores = computeHostNumPhysicalCores(); | |||
1155 | return NumCores; | |||
1156 | } | |||
1157 | ||||
1158 | #if defined(__i386__) || defined(_M_IX86) || \ | |||
1159 | defined(__x86_64__1) || defined(_M_X64) | |||
1160 | bool sys::getHostCPUFeatures(StringMap<bool> &Features) { | |||
1161 | unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0; | |||
1162 | unsigned MaxLevel; | |||
1163 | union { | |||
1164 | unsigned u[3]; | |||
1165 | char c[12]; | |||
1166 | } text; | |||
1167 | ||||
1168 | if (getX86CpuIDAndInfo(0, &MaxLevel, text.u + 0, text.u + 2, text.u + 1) || | |||
1169 | MaxLevel < 1) | |||
1170 | return false; | |||
1171 | ||||
1172 | getX86CpuIDAndInfo(1, &EAX, &EBX, &ECX, &EDX); | |||
1173 | ||||
1174 | Features["cmov"] = (EDX >> 15) & 1; | |||
1175 | Features["mmx"] = (EDX >> 23) & 1; | |||
1176 | Features["sse"] = (EDX >> 25) & 1; | |||
1177 | Features["sse2"] = (EDX >> 26) & 1; | |||
1178 | ||||
1179 | Features["sse3"] = (ECX >> 0) & 1; | |||
1180 | Features["pclmul"] = (ECX >> 1) & 1; | |||
1181 | Features["ssse3"] = (ECX >> 9) & 1; | |||
1182 | Features["cx16"] = (ECX >> 13) & 1; | |||
1183 | Features["sse4.1"] = (ECX >> 19) & 1; | |||
1184 | Features["sse4.2"] = (ECX >> 20) & 1; | |||
1185 | Features["movbe"] = (ECX >> 22) & 1; | |||
1186 | Features["popcnt"] = (ECX >> 23) & 1; | |||
1187 | Features["aes"] = (ECX >> 25) & 1; | |||
1188 | Features["rdrnd"] = (ECX >> 30) & 1; | |||
1189 | ||||
1190 | // If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV | |||
1191 | // indicates that the AVX registers will be saved and restored on context | |||
1192 | // switch, then we have full AVX support. | |||
1193 | bool HasAVXSave = ((ECX >> 27) & 1) && ((ECX >> 28) & 1) && | |||
1194 | !getX86XCR0(&EAX, &EDX) && ((EAX & 0x6) == 0x6); | |||
1195 | // AVX512 requires additional context to be saved by the OS. | |||
1196 | bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0); | |||
1197 | ||||
1198 | Features["avx"] = HasAVXSave; | |||
1199 | Features["fma"] = ((ECX >> 12) & 1) && HasAVXSave; | |||
1200 | // Only enable XSAVE if OS has enabled support for saving YMM state. | |||
1201 | Features["xsave"] = ((ECX >> 26) & 1) && HasAVXSave; | |||
1202 | Features["f16c"] = ((ECX >> 29) & 1) && HasAVXSave; | |||
1203 | ||||
1204 | unsigned MaxExtLevel; | |||
1205 | getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX); | |||
1206 | ||||
1207 | bool HasExtLeaf1 = MaxExtLevel >= 0x80000001 && | |||
1208 | !getX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX); | |||
1209 | Features["sahf"] = HasExtLeaf1 && ((ECX >> 0) & 1); | |||
1210 | Features["lzcnt"] = HasExtLeaf1 && ((ECX >> 5) & 1); | |||
1211 | Features["sse4a"] = HasExtLeaf1 && ((ECX >> 6) & 1); | |||
1212 | Features["prfchw"] = HasExtLeaf1 && ((ECX >> 8) & 1); | |||
1213 | Features["xop"] = HasExtLeaf1 && ((ECX >> 11) & 1) && HasAVXSave; | |||
1214 | Features["lwp"] = HasExtLeaf1 && ((ECX >> 15) & 1); | |||
1215 | Features["fma4"] = HasExtLeaf1 && ((ECX >> 16) & 1) && HasAVXSave; | |||
1216 | Features["tbm"] = HasExtLeaf1 && ((ECX >> 21) & 1); | |||
1217 | Features["mwaitx"] = HasExtLeaf1 && ((ECX >> 29) & 1); | |||
1218 | ||||
1219 | bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 && | |||
1220 | !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX); | |||
1221 | Features["clzero"] = HasExtLeaf8 && ((EBX >> 0) & 1); | |||
1222 | ||||
1223 | bool HasLeaf7 = | |||
1224 | MaxLevel >= 7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX); | |||
1225 | ||||
1226 | Features["fsgsbase"] = HasLeaf7 && ((EBX >> 0) & 1); | |||
1227 | Features["sgx"] = HasLeaf7 && ((EBX >> 2) & 1); | |||
1228 | Features["bmi"] = HasLeaf7 && ((EBX >> 3) & 1); | |||
1229 | // AVX2 is only supported if we have the OS save support from AVX. | |||
1230 | Features["avx2"] = HasLeaf7 && ((EBX >> 5) & 1) && HasAVXSave; | |||
1231 | Features["bmi2"] = HasLeaf7 && ((EBX >> 8) & 1); | |||
1232 | Features["rtm"] = HasLeaf7 && ((EBX >> 11) & 1); | |||
1233 | // AVX512 is only supported if the OS supports the context save for it. | |||
1234 | Features["avx512f"] = HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save; | |||
1235 | Features["avx512dq"] = HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save; | |||
1236 | Features["rdseed"] = HasLeaf7 && ((EBX >> 18) & 1); | |||
1237 | Features["adx"] = HasLeaf7 && ((EBX >> 19) & 1); | |||
1238 | Features["avx512ifma"] = HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save; | |||
1239 | Features["clflushopt"] = HasLeaf7 && ((EBX >> 23) & 1); | |||
1240 | Features["clwb"] = HasLeaf7 && ((EBX >> 24) & 1); | |||
1241 | Features["avx512pf"] = HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save; | |||
1242 | Features["avx512er"] = HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save; | |||
1243 | Features["avx512cd"] = HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save; | |||
1244 | Features["sha"] = HasLeaf7 && ((EBX >> 29) & 1); | |||
1245 | Features["avx512bw"] = HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save; | |||
1246 | Features["avx512vl"] = HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save; | |||
1247 | ||||
1248 | Features["prefetchwt1"] = HasLeaf7 && ((ECX >> 0) & 1); | |||
1249 | Features["avx512vbmi"] = HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save; | |||
1250 | Features["pku"] = HasLeaf7 && ((ECX >> 4) & 1); | |||
1251 | Features["avx512vbmi2"] = HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save; | |||
1252 | Features["shstk"] = HasLeaf7 && ((ECX >> 7) & 1); | |||
1253 | Features["gfni"] = HasLeaf7 && ((ECX >> 8) & 1); | |||
1254 | Features["vaes"] = HasLeaf7 && ((ECX >> 9) & 1) && HasAVXSave; | |||
1255 | Features["vpclmulqdq"] = HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave; | |||
1256 | Features["avx512vnni"] = HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save; | |||
1257 | Features["avx512bitalg"] = HasLeaf7 && ((ECX >> 12) & 1) && HasAVX512Save; | |||
1258 | Features["avx512vpopcntdq"] = HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save; | |||
1259 | Features["rdpid"] = HasLeaf7 && ((ECX >> 22) & 1); | |||
1260 | ||||
1261 | Features["ibt"] = HasLeaf7 && ((EDX >> 20) & 1); | |||
1262 | ||||
1263 | bool HasLeafD = MaxLevel >= 0xd && | |||
1264 | !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX); | |||
1265 | ||||
1266 | // Only enable XSAVE if OS has enabled support for saving YMM state. | |||
1267 | Features["xsaveopt"] = HasLeafD && ((EAX >> 0) & 1) && HasAVXSave; | |||
1268 | Features["xsavec"] = HasLeafD && ((EAX >> 1) & 1) && HasAVXSave; | |||
1269 | Features["xsaves"] = HasLeafD && ((EAX >> 3) & 1) && HasAVXSave; | |||
1270 | ||||
1271 | return true; | |||
1272 | } | |||
1273 | #elif defined(__linux__1) && (defined(__arm__) || defined(__aarch64__)) | |||
1274 | bool sys::getHostCPUFeatures(StringMap<bool> &Features) { | |||
1275 | std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); | |||
1276 | if (!P) | |||
1277 | return false; | |||
1278 | ||||
1279 | SmallVector<StringRef, 32> Lines; | |||
1280 | P->getBuffer().split(Lines, "\n"); | |||
1281 | ||||
1282 | SmallVector<StringRef, 32> CPUFeatures; | |||
1283 | ||||
1284 | // Look for the CPU features. | |||
1285 | for (unsigned I = 0, E = Lines.size(); I != E; ++I) | |||
1286 | if (Lines[I].startswith("Features")) { | |||
1287 | Lines[I].split(CPUFeatures, ' '); | |||
1288 | break; | |||
1289 | } | |||
1290 | ||||
1291 | #if defined(__aarch64__) | |||
1292 | // Keep track of which crypto features we have seen | |||
1293 | enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 }; | |||
1294 | uint32_t crypto = 0; | |||
1295 | #endif | |||
1296 | ||||
1297 | for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) { | |||
1298 | StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I]) | |||
1299 | #if defined(__aarch64__) | |||
1300 | .Case("asimd", "neon") | |||
1301 | .Case("fp", "fp-armv8") | |||
1302 | .Case("crc32", "crc") | |||
1303 | #else | |||
1304 | .Case("half", "fp16") | |||
1305 | .Case("neon", "neon") | |||
1306 | .Case("vfpv3", "vfp3") | |||
1307 | .Case("vfpv3d16", "d16") | |||
1308 | .Case("vfpv4", "vfp4") | |||
1309 | .Case("idiva", "hwdiv-arm") | |||
1310 | .Case("idivt", "hwdiv") | |||
1311 | #endif | |||
1312 | .Default(""); | |||
1313 | ||||
1314 | #if defined(__aarch64__) | |||
1315 | // We need to check crypto separately since we need all of the crypto | |||
1316 | // extensions to enable the subtarget feature | |||
1317 | if (CPUFeatures[I] == "aes") | |||
1318 | crypto |= CAP_AES; | |||
1319 | else if (CPUFeatures[I] == "pmull") | |||
1320 | crypto |= CAP_PMULL; | |||
1321 | else if (CPUFeatures[I] == "sha1") | |||
1322 | crypto |= CAP_SHA1; | |||
1323 | else if (CPUFeatures[I] == "sha2") | |||
1324 | crypto |= CAP_SHA2; | |||
1325 | #endif | |||
1326 | ||||
1327 | if (LLVMFeatureStr != "") | |||
1328 | Features[LLVMFeatureStr] = true; | |||
1329 | } | |||
1330 | ||||
1331 | #if defined(__aarch64__) | |||
1332 | // If we have all crypto bits we can add the feature | |||
1333 | if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2)) | |||
1334 | Features["crypto"] = true; | |||
1335 | #endif | |||
1336 | ||||
1337 | return true; | |||
1338 | } | |||
1339 | #else | |||
1340 | bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; } | |||
1341 | #endif | |||
1342 | ||||
1343 | std::string sys::getProcessTriple() { | |||
1344 | std::string TargetTripleString = updateTripleOSVersion(LLVM_HOST_TRIPLE"x86_64-pc-linux-gnu"); | |||
1345 | Triple PT(Triple::normalize(TargetTripleString)); | |||
1346 | ||||
1347 | if (sizeof(void *) == 8 && PT.isArch32Bit()) | |||
1348 | PT = PT.get64BitArchVariant(); | |||
1349 | if (sizeof(void *) == 4 && PT.isArch64Bit()) | |||
1350 | PT = PT.get32BitArchVariant(); | |||
1351 | ||||
1352 | return PT.str(); | |||
1353 | } |