Skip to content

Commit f22f88b

Browse files
mattjgallowayfacebook-github-bot
authored andcommitted
Save and restore rbx across cpuid on Windows
Summary: We need to preserve `rbx` across the call to `cpuid` on Windows. This becomes obvious when compiling under ASan where presumably due to high register pressure, we end up in a situation where `rbx` is clobbered by `cpuid` but the compiler did not expect it to be clobbered. This is fixed in clang upstream here: llvm/llvm-project#49477 https://reviews.llvm.org/D101338 However we use an older compiler (LLVM12.0.1) which does not have the patch yet. Reviewed By: yfeldblum Differential Revision: D35229538 fbshipit-source-id: 265835fb0e79e3a209dbce4fe82e8baa43e3d6ba
1 parent ecc04a0 commit f22f88b

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

folly/CpuId.h

+35
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class CpuId {
4242
// statically linked binaries which don't depend on the PLT)
4343
FOLLY_ALWAYS_INLINE CpuId() {
4444
#if defined(_MSC_VER) && (FOLLY_X64 || defined(_M_IX86))
45+
#if !defined(__clang__)
4546
int reg[4];
4647
__cpuid(static_cast<int*>(reg), 0);
4748
const int n = reg[0];
@@ -55,6 +56,40 @@ class CpuId {
5556
f7b_ = uint32_t(reg[1]);
5657
f7c_ = uint32_t(reg[2]);
5758
}
59+
#else
60+
// Clang compiler has a bug (fixed in https://reviews.llvm.org/D101338) in
61+
// which the `__cpuid` intrinsic does not save and restore `rbx` as it needs
62+
// to due to being a reserved register. So in that case, do the `cpuid`
63+
// ourselves. Clang supports inline assembly anyway.
64+
uint32_t n;
65+
__asm__(
66+
"pushq %%rbx\n\t"
67+
"cpuid\n\t"
68+
"popq %%rbx\n\t"
69+
: "=a"(n)
70+
: "a"(0)
71+
: "rcx", "rdx");
72+
if (n >= 1) {
73+
uint32_t f1a;
74+
__asm__(
75+
"pushq %%rbx\n\t"
76+
"cpuid\n\t"
77+
"popq %%rbx\n\t"
78+
: "=a"(f1a), "=c"(f1c_), "=d"(f1d_)
79+
: "a"(1)
80+
:);
81+
}
82+
if (n >= 7) {
83+
__asm__(
84+
"pushq %%rbx\n\t"
85+
"cpuid\n\t"
86+
"movq %%rbx, %%rax\n\t"
87+
"popq %%rbx"
88+
: "=a"(f7b_), "=c"(f7c_)
89+
: "a"(7), "c"(0)
90+
: "rdx");
91+
}
92+
#endif
5893
#elif defined(__i386__) && defined(__PIC__) && !defined(__clang__) && \
5994
defined(__GNUC__)
6095
// The following block like the normal cpuid branch below, but gcc

0 commit comments

Comments
 (0)