Commit 95209f9d authored by Philip Pronin's avatar Philip Pronin Committed by Facebook Github Bot

fix silent eax clobbering in CpuId ctor

Summary:
`cpuid` uses all of `eax`, `ebx`, `ecx`, `edx` for output, but we
aren't providing such information to GCC in a couple of cases, which might
result in incorrect code being produced;

GCC (unlike clang) doesn't allow the same register to appear both in input and
clobber list, so put `eax` into output list where required.

Reviewed By: ot, lbrandy

Differential Revision: D4961841

fbshipit-source-id: 07ca1977373496bfd794d3b0c8a4ba21333820e4
parent af5ed37b
...@@ -33,7 +33,7 @@ namespace folly { ...@@ -33,7 +33,7 @@ namespace folly {
class CpuId { class CpuId {
public: public:
// Always inline in order for this to be usable from a __ifunc__. // Always inline in order for this to be usable from a __ifunc__.
// In shared library mde, a __ifunc__ runs at relocation time, while the // In shared library mode, a __ifunc__ runs at relocation time, while the
// PLT hasn't been fully populated yet; thus, ifuncs cannot use symbols // PLT hasn't been fully populated yet; thus, ifuncs cannot use symbols
// with potentially external linkage. (This issue is less likely in opt // with potentially external linkage. (This issue is less likely in opt
// mode since inlining happens more likely, and it doesn't happen for // mode since inlining happens more likely, and it doesn't happen for
...@@ -56,7 +56,7 @@ class CpuId { ...@@ -56,7 +56,7 @@ class CpuId {
#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && \ #elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && \
defined(__GNUC__) defined(__GNUC__)
// The following block like the normal cpuid branch below, but gcc // The following block like the normal cpuid branch below, but gcc
// reserves ebx for use of it's pic register so we must specially // reserves ebx for use of its pic register so we must specially
// handle the save and restore to avoid clobbering the register // handle the save and restore to avoid clobbering the register
uint32_t n; uint32_t n;
__asm__( __asm__(
...@@ -65,13 +65,14 @@ class CpuId { ...@@ -65,13 +65,14 @@ class CpuId {
"popl %%ebx\n\t" "popl %%ebx\n\t"
: "=a"(n) : "=a"(n)
: "a"(0) : "a"(0)
: "edx", "ecx"); : "ecx", "edx");
if (n >= 1) { if (n >= 1) {
uint32_t f1a;
__asm__( __asm__(
"pushl %%ebx\n\t" "pushl %%ebx\n\t"
"cpuid\n\t" "cpuid\n\t"
"popl %%ebx\n\t" "popl %%ebx\n\t"
: "=c"(f1c_), "=d"(f1d_) : "=a"(f1a), "=c"(f1c_), "=d"(f1d_)
: "a"(1) : "a"(1)
:); :);
} }
...@@ -87,12 +88,17 @@ class CpuId { ...@@ -87,12 +88,17 @@ class CpuId {
} }
#elif FOLLY_X64 || defined(__i386__) #elif FOLLY_X64 || defined(__i386__)
uint32_t n; uint32_t n;
__asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "edx", "ecx"); __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
if (n >= 1) { if (n >= 1) {
__asm__("cpuid" : "=c"(f1c_), "=d"(f1d_) : "a"(1) : "ebx"); uint32_t f1a;
__asm__("cpuid" : "=a"(f1a), "=c"(f1c_), "=d"(f1d_) : "a"(1) : "ebx");
} }
if (n >= 7) { if (n >= 7) {
__asm__("cpuid" : "=b"(f7b_), "=c"(f7c_) : "a"(7), "c"(0) : "edx"); uint32_t f7a;
__asm__("cpuid"
: "=a"(f7a), "=b"(f7b_), "=c"(f7c_)
: "a"(7), "c"(0)
: "edx");
} }
#endif #endif
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment