From 95209f9d06df94908db7dbf5a4067eca11b9da59 Mon Sep 17 00:00:00 2001 From: Philip Pronin Date: Thu, 27 Apr 2017 10:06:51 -0700 Subject: [PATCH] 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 --- folly/CpuId.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/folly/CpuId.h b/folly/CpuId.h index 5e06513c..bbd36c21 100644 --- a/folly/CpuId.h +++ b/folly/CpuId.h @@ -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 } -- 2.34.1