50
50
#if defined(__sun__) && defined(__svr4__)
51
51
#include < kstat.h>
52
52
#endif
53
- #if defined(__GNUC__) || defined(__clang__)
54
- #if defined(__i386__) || defined(__x86_64__)
55
- #include < cpuid.h>
56
- #endif
57
- #endif
58
53
59
54
#define DEBUG_TYPE " host-detection"
60
55
@@ -526,15 +521,68 @@ StringRef sys::detail::getHostCPUNameForBPF() {
526
521
#endif
527
522
}
528
523
529
- #if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \
530
- defined (_M_X64)
524
+ #if defined(__i386__) || defined(_M_IX86) || \
525
+ defined (__x86_64__) || defined(_M_X64)
526
+
527
+ // The check below for i386 was copied from clang's cpuid.h (__get_cpuid_max).
528
+ // Check motivated by bug reports for OpenSSL crashing on CPUs without CPUID
529
+ // support. Consequently, for i386, the presence of CPUID is checked first
530
+ // via the corresponding eflags bit.
531
+ // Removal of cpuid.h header motivated by PR30384
532
+ // Header cpuid.h and method __get_cpuid_max are not used in llvm, clang, openmp
533
+ // or test-suite, but are used in external projects e.g. libstdcxx
534
+ static bool isCpuIdSupported() {
535
+ #if defined(__GNUC__) || defined(__clang__)
536
+ #if defined(__i386__)
537
+ int __cpuid_supported;
538
+ __asm__ (" pushfl\n "
539
+ " popl %%eax\n "
540
+ " movl %%eax,%%ecx\n "
541
+ " xorl $0x00200000,%%eax\n "
542
+ " pushl %%eax\n "
543
+ " popfl\n "
544
+ " pushfl\n "
545
+ " popl %%eax\n "
546
+ " movl $0,%0\n "
547
+ " cmpl %%eax,%%ecx\n "
548
+ " je 1f\n "
549
+ " movl $1,%0\n "
550
+ " 1:"
551
+ : " =r" (__cpuid_supported)
552
+ :
553
+ : " eax" , " ecx" );
554
+ if (!__cpuid_supported)
555
+ return false ;
556
+ #endif
557
+ return true ;
558
+ #endif
559
+ return true ;
560
+ }
531
561
532
562
// / getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
533
563
// / the specified arguments. If we can't run cpuid on the host, return true.
534
564
static bool getX86CpuIDAndInfo (unsigned value, unsigned *rEAX, unsigned *rEBX,
535
565
unsigned *rECX, unsigned *rEDX) {
536
566
#if defined(__GNUC__) || defined(__clang__)
537
- return !__get_cpuid (value, rEAX, rEBX, rECX, rEDX);
567
+ #if defined(__x86_64__)
568
+ // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
569
+ // FIXME: should we save this for Clang?
570
+ __asm__ (" movq\t %%rbx, %%rsi\n\t "
571
+ " cpuid\n\t "
572
+ " xchgq\t %%rbx, %%rsi\n\t "
573
+ : " =a" (*rEAX), " =S" (*rEBX), " =c" (*rECX), " =d" (*rEDX)
574
+ : " a" (value));
575
+ return false ;
576
+ #elif defined(__i386__)
577
+ __asm__ (" movl\t %%ebx, %%esi\n\t "
578
+ " cpuid\n\t "
579
+ " xchgl\t %%ebx, %%esi\n\t "
580
+ : " =a" (*rEAX), " =S" (*rEBX), " =c" (*rECX), " =d" (*rEDX)
581
+ : " a" (value));
582
+ return false ;
583
+ #else
584
+ return true ;
585
+ #endif
538
586
#elif defined(_MSC_VER)
539
587
// The MSVC intrinsic is portable across x86 and x64.
540
588
int registers[4 ];
@@ -561,6 +609,9 @@ VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
561
609
else
562
610
*MaxLeaf = 0 ;
563
611
612
+ if (!isCpuIdSupported ())
613
+ return VendorSignatures::UNKNOWN;
614
+
564
615
if (getX86CpuIDAndInfo (0 , MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1 )
565
616
return VendorSignatures::UNKNOWN;
566
617
@@ -588,12 +639,26 @@ using namespace llvm::sys::detail::x86;
588
639
static bool getX86CpuIDAndInfoEx (unsigned value, unsigned subleaf,
589
640
unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
590
641
unsigned *rEDX) {
591
- // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang
592
- // are such that __cpuidex is defined within cpuid.h for both, we can remove
593
- // the __get_cpuid_count function and share the MSVC implementation between
594
- // all three.
595
642
#if defined(__GNUC__) || defined(__clang__)
596
- return !__get_cpuid_count (value, subleaf, rEAX, rEBX, rECX, rEDX);
643
+ #if defined(__x86_64__)
644
+ // gcc doesn't know cpuid would clobber ebx/rbx. Preserve it manually.
645
+ // FIXME: should we save this for Clang?
646
+ __asm__ (" movq\t %%rbx, %%rsi\n\t "
647
+ " cpuid\n\t "
648
+ " xchgq\t %%rbx, %%rsi\n\t "
649
+ : " =a" (*rEAX), " =S" (*rEBX), " =c" (*rECX), " =d" (*rEDX)
650
+ : " a" (value), " c" (subleaf));
651
+ return false ;
652
+ #elif defined(__i386__)
653
+ __asm__ (" movl\t %%ebx, %%esi\n\t "
654
+ " cpuid\n\t "
655
+ " xchgl\t %%ebx, %%esi\n\t "
656
+ : " =a" (*rEAX), " =S" (*rEBX), " =c" (*rECX), " =d" (*rEDX)
657
+ : " a" (value), " c" (subleaf));
658
+ return false ;
659
+ #else
660
+ return true ;
661
+ #endif
597
662
#elif defined(_MSC_VER)
598
663
int registers[4 ];
599
664
__cpuidex (registers, value, subleaf);
@@ -609,9 +674,6 @@ static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
609
674
610
675
// Read control register 0 (XCR0). Used to detect features such as AVX.
611
676
static bool getX86XCR0 (unsigned *rEAX, unsigned *rEDX) {
612
- // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang
613
- // are such that _xgetbv is supported by both, we can unify the implementation
614
- // with MSVC and remove all inline assembly.
615
677
#if defined(__GNUC__) || defined(__clang__)
616
678
// Check xgetbv; this uses a .byte sequence instead of the instruction
617
679
// directly because older assemblers do not include support for xgetbv and
0 commit comments