Skip to content

Commit 3cec2a1

Browse files
committed
[X86] Fix the implementation of __readcr3/__writecr3 to work in 64-bit mode
We need to use a 64-bit type in 64-bit mode so a 64-bit register will get used in the generated assembly. I've also changed the constraints to just use "r" intead of "q". "q" forces to a only an a/b/c/d register in 32-bit mode, but I see no reason that would matter here. Fixes Nico's note in PR19301 over 4 years ago. Differential Revision: https://reviews.llvm.org/D70101
1 parent 1ee84e5 commit 3cec2a1

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

clang/lib/Headers/intrin.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
/* Define the default attributes for the functions in this file. */
3737
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
3838

39+
#if __x86_64__
40+
#define __LPTRINT_TYPE__ __int64
41+
#else
42+
#define __LPTRINT_TYPE__ long
43+
#endif
44+
3945
#ifdef __cplusplus
4046
extern "C" {
4147
#endif
@@ -94,8 +100,7 @@ void __outword(unsigned short, unsigned short);
94100
void __outwordstring(unsigned short, unsigned short *, unsigned long);
95101
unsigned long __readcr0(void);
96102
unsigned long __readcr2(void);
97-
static __inline__
98-
unsigned long __readcr3(void);
103+
unsigned __LPTRINT_TYPE__ __readcr3(void);
99104
unsigned long __readcr4(void);
100105
unsigned long __readcr8(void);
101106
unsigned int __readdr(unsigned int);
@@ -132,7 +137,7 @@ void __vmx_vmptrst(unsigned __int64 *);
132137
void __wbinvd(void);
133138
void __writecr0(unsigned int);
134139
static __inline__
135-
void __writecr3(unsigned int);
140+
void __writecr3(unsigned __INTPTR_TYPE__);
136141
void __writecr4(unsigned int);
137142
void __writecr8(unsigned int);
138143
void __writedr(unsigned int, unsigned int);
@@ -565,24 +570,26 @@ __readmsr(unsigned long __register) {
565570
__asm__ ("rdmsr" : "=d"(__edx), "=a"(__eax) : "c"(__register));
566571
return (((unsigned __int64)__edx) << 32) | (unsigned __int64)__eax;
567572
}
573+
#endif
568574

569-
static __inline__ unsigned long __DEFAULT_FN_ATTRS
575+
static __inline__ unsigned __LPTRINT_TYPE__ __DEFAULT_FN_ATTRS
570576
__readcr3(void) {
571-
unsigned long __cr3_val;
572-
__asm__ __volatile__ ("mov %%cr3, %0" : "=q"(__cr3_val) : : "memory");
577+
unsigned __LPTRINT_TYPE__ __cr3_val;
578+
__asm__ __volatile__ ("mov %%cr3, %0" : "=r"(__cr3_val) : : "memory");
573579
return __cr3_val;
574580
}
575581

576582
static __inline__ void __DEFAULT_FN_ATTRS
577-
__writecr3(unsigned int __cr3_val) {
578-
__asm__ ("mov %0, %%cr3" : : "q"(__cr3_val) : "memory");
583+
__writecr3(unsigned __INTPTR_TYPE__ __cr3_val) {
584+
__asm__ ("mov %0, %%cr3" : : "r"(__cr3_val) : "memory");
579585
}
580-
#endif
581586

582587
#ifdef __cplusplus
583588
}
584589
#endif
585590

591+
#undef __LPTRINT_TYPE__
592+
586593
#undef __DEFAULT_FN_ATTRS
587594

588595
#endif /* __INTRIN_H */

clang/test/Headers/ms-intrin.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,8 @@ void f() {
5656
__nop();
5757
__readmsr(0);
5858

59-
// FIXME: Call these in 64-bit too once the intrinsics have been fixed to
60-
// work there, PR19301
61-
#ifndef _M_X64
6259
__readcr3();
6360
__writecr3(0);
64-
#endif
6561

6662
#ifdef _M_ARM
6763
__dmb(_ARM_BARRIER_ISHST);

0 commit comments

Comments
 (0)