fix silent eax clobbering in CpuId ctor
authorPhilip Pronin <philipp@fb.com>
Thu, 27 Apr 2017 17:06:51 +0000 (10:06 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 27 Apr 2017 17:21:35 +0000 (10:21 -0700)
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

folly/CpuId.h

index 5e06513..bbd36c2 100644 (file)
@@ -33,7 +33,7 @@ namespace folly {
 class CpuId {
  public:
   // 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
   // with potentially external linkage. (This issue is less likely in opt
   // mode since inlining happens more likely, and it doesn't happen for
@@ -56,7 +56,7 @@ class CpuId {
 #elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && \
     defined(__GNUC__)
     // 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
     uint32_t n;
     __asm__(
@@ -65,13 +65,14 @@ class CpuId {
         "popl %%ebx\n\t"
         : "=a"(n)
         : "a"(0)
-        : "edx", "ecx");
+        : "ecx", "edx");
     if (n >= 1) {
+      uint32_t f1a;
       __asm__(
           "pushl %%ebx\n\t"
           "cpuid\n\t"
           "popl %%ebx\n\t"
-          : "=c"(f1c_), "=d"(f1d_)
+          : "=a"(f1a), "=c"(f1c_), "=d"(f1d_)
           : "a"(1)
           :);
     }
@@ -87,12 +88,17 @@ class CpuId {
     }
 #elif FOLLY_X64 || defined(__i386__)
     uint32_t n;
-    __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "edx", "ecx");
+    __asm__("cpuid" : "=a"(n) : "a"(0) : "ebx", "ecx", "edx");
     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) {
-      __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
   }