5050#if defined(__sun__) && defined(__svr4__)
5151#include < kstat.h>
5252#endif
53- #if defined(__GNUC__) || defined(__clang__)
54- #include < cpuid.h>
55- #endif
5653
5754#define DEBUG_TYPE " host-detection"
5855
@@ -524,15 +521,68 @@ StringRef sys::detail::getHostCPUNameForBPF() {
524521#endif
525522}
526523
527- #if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \
528- 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+ }
529561
530562// / getX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in
531563// / the specified arguments. If we can't run cpuid on the host, return true.
532564static bool getX86CpuIDAndInfo (unsigned value, unsigned *rEAX, unsigned *rEBX,
533565 unsigned *rECX, unsigned *rEDX) {
534566#if defined(__GNUC__) || defined(__clang__)
535- 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
536586#elif defined(_MSC_VER)
537587 // The MSVC intrinsic is portable across x86 and x64.
538588 int registers[4 ];
@@ -559,6 +609,9 @@ VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
559609 else
560610 *MaxLeaf = 0 ;
561611
612+ if (!isCpuIdSupported ())
613+ return VendorSignatures::UNKNOWN;
614+
562615 if (getX86CpuIDAndInfo (0 , MaxLeaf, &EBX, &ECX, &EDX) || *MaxLeaf < 1 )
563616 return VendorSignatures::UNKNOWN;
564617
@@ -586,12 +639,26 @@ using namespace llvm::sys::detail::x86;
586639static bool getX86CpuIDAndInfoEx (unsigned value, unsigned subleaf,
587640 unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
588641 unsigned *rEDX) {
589- // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang
590- // are such that __cpuidex is defined within cpuid.h for both, we can remove
591- // the __get_cpuid_count function and share the MSVC implementation between
592- // all three.
593642#if defined(__GNUC__) || defined(__clang__)
594- 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
595662#elif defined(_MSC_VER)
596663 int registers[4 ];
597664 __cpuidex (registers, value, subleaf);
@@ -607,9 +674,6 @@ static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
607674
608675// Read control register 0 (XCR0). Used to detect features such as AVX.
609676static bool getX86XCR0 (unsigned *rEAX, unsigned *rEDX) {
610- // TODO(boomanaiden154): When the minimum toolchain versions for gcc and clang
611- // are such that _xgetbv is supported by both, we can unify the implementation
612- // with MSVC and remove all inline assembly.
613677#if defined(__GNUC__) || defined(__clang__)
614678 // Check xgetbv; this uses a .byte sequence instead of the instruction
615679 // directly because older assemblers do not include support for xgetbv and
0 commit comments