Skip to content

Commit

Permalink
[X86] Implement __readgsqword (and the rest) as builtins (PR32373)
Browse files Browse the repository at this point in the history
It seems MS headers have started using __readgsqword, and since it's
used in a header that doesn't include intrin.h, we can't implement it as
an inline function anymore.

That was already the case for __readfsdword, which Saleem added support
for in r220859. This patch reuses that codegen to implement all of
__read[fg]s{byte,word,dword,qword}.

Differential Revision: https://reviews.llvm.org/D31248

llvm-svn: 298538
  • Loading branch information
zmodem committed Mar 22, 2017
1 parent dc13921 commit 043f402
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 57 deletions.
1 change: 0 additions & 1 deletion clang/include/clang/Basic/Builtins.def
Expand Up @@ -766,7 +766,6 @@ LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__popcnt64, "ULLiULLi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__readfsdword, "ULiULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl8, "UcUcUc", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_rotl16, "UsUsUc", "n", ALL_MS_LANGUAGES)
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/BuiltinsX86.def
Expand Up @@ -1832,6 +1832,16 @@ TARGET_HEADER_BUILTIN(__stosb, "vUc*Ucz", "nh", "intrin.h", ALL_MS_LANGUAGES, ""
TARGET_HEADER_BUILTIN(__int2c, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__ud2, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "")

TARGET_HEADER_BUILTIN(__readfsbyte, "UcULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsword, "UsULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsdword, "ULiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readfsqword, "ULLiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")

TARGET_HEADER_BUILTIN(__readgsbyte, "UcULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsword, "UsULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsdword, "ULiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")
TARGET_HEADER_BUILTIN(__readgsqword, "ULLiULi", "nh", "intrin.h", ALL_MS_LANGUAGES, "")

#undef BUILTIN
#undef TARGET_BUILTIN
#undef TARGET_HEADER_BUILTIN
34 changes: 24 additions & 10 deletions clang/lib/CodeGen/CGBuiltin.cpp
Expand Up @@ -2238,16 +2238,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI_InterlockedXor16:
case Builtin::BI_InterlockedXor:
return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E));
case Builtin::BI__readfsdword: {
llvm::Type *IntTy = ConvertType(E->getType());
Value *IntToPtr =
Builder.CreateIntToPtr(EmitScalarExpr(E->getArg(0)),
llvm::PointerType::get(IntTy, 257));
LoadInst *Load = Builder.CreateAlignedLoad(
IntTy, IntToPtr, getContext().getTypeAlignInChars(E->getType()));
Load->setVolatile(true);
return RValue::get(Load);
}

case Builtin::BI__exception_code:
case Builtin::BI_exception_code:
Expand Down Expand Up @@ -8005,6 +7995,30 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
CS.setAttributes(NoReturnAttr);
return CS.getInstruction();
}
case X86::BI__readfsbyte:
case X86::BI__readfsword:
case X86::BI__readfsdword:
case X86::BI__readfsqword: {
llvm::Type *IntTy = ConvertType(E->getType());
Value *Ptr = Builder.CreateIntToPtr(EmitScalarExpr(E->getArg(0)),
llvm::PointerType::get(IntTy, 257));
LoadInst *Load = Builder.CreateAlignedLoad(
IntTy, Ptr, getContext().getTypeAlignInChars(E->getType()));
Load->setVolatile(true);
return Load;
}
case X86::BI__readgsbyte:
case X86::BI__readgsword:
case X86::BI__readgsdword:
case X86::BI__readgsqword: {
llvm::Type *IntTy = ConvertType(E->getType());
Value *Ptr = Builder.CreateIntToPtr(EmitScalarExpr(E->getArg(0)),
llvm::PointerType::get(IntTy, 256));
LoadInst *Load = Builder.CreateAlignedLoad(
IntTy, Ptr, getContext().getTypeAlignInChars(E->getType()));
Load->setVolatile(true);
return Load;
}
}
}

Expand Down
43 changes: 0 additions & 43 deletions clang/lib/Headers/intrin.h
Expand Up @@ -869,50 +869,7 @@ _InterlockedCompareExchange64_rel(__int64 volatile *_Destination,
return _Comparand;
}
#endif
/*----------------------------------------------------------------------------*\
|* readfs, readgs
|* (Pointers in address space #256 and #257 are relative to the GS and FS
|* segment registers, respectively.)
\*----------------------------------------------------------------------------*/
#define __ptr_to_addr_space(__addr_space_nbr, __type, __offset) \
((volatile __type __attribute__((__address_space__(__addr_space_nbr)))*) \
(__offset))

#ifdef __i386__
static __inline__ unsigned char __DEFAULT_FN_ATTRS
__readfsbyte(unsigned long __offset) {
return *__ptr_to_addr_space(257, unsigned char, __offset);
}
static __inline__ unsigned short __DEFAULT_FN_ATTRS
__readfsword(unsigned long __offset) {
return *__ptr_to_addr_space(257, unsigned short, __offset);
}
static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
__readfsqword(unsigned long __offset) {
return *__ptr_to_addr_space(257, unsigned __int64, __offset);
}
#endif
#ifdef __x86_64__
static __inline__ unsigned char __DEFAULT_FN_ATTRS
__readgsbyte(unsigned long __offset) {
return *__ptr_to_addr_space(256, unsigned char, (unsigned long long)__offset);
}
static __inline__ unsigned short __DEFAULT_FN_ATTRS
__readgsword(unsigned long __offset) {
return *__ptr_to_addr_space(256, unsigned short,
(unsigned long long)__offset);
}
static __inline__ unsigned long __DEFAULT_FN_ATTRS
__readgsdword(unsigned long __offset) {
return *__ptr_to_addr_space(256, unsigned long, (unsigned long long)__offset);
}
static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS
__readgsqword(unsigned long __offset) {
return *__ptr_to_addr_space(256, unsigned __int64,
(unsigned long long)__offset);
}
#endif
#undef __ptr_to_addr_space
/*----------------------------------------------------------------------------*\
|* movs, stos
\*----------------------------------------------------------------------------*/
Expand Down
65 changes: 62 additions & 3 deletions clang/test/CodeGen/ms-x86-intrinsics.c
Expand Up @@ -6,15 +6,37 @@
// RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X64

#if defined(__i386__)
char test__readfsbyte(unsigned long Offset) {
return __readfsbyte(Offset);
}
// CHECK-I386-LABEL: define signext i8 @test__readfsbyte(i32 %Offset)
// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i8 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i8, i8 addrspace(257)* [[PTR]], align 1
// CHECK-I386: ret i8 [[VALUE:%[0-9]+]]

short test__readfsword(unsigned long Offset) {
return __readfsword(Offset);
}
// CHECK-I386-LABEL: define signext i16 @test__readfsword(i32 %Offset)
// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i16 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i16, i16 addrspace(257)* [[PTR]], align 2
// CHECK-I386: ret i16 [[VALUE:%[0-9]+]]

long test__readfsdword(unsigned long Offset) {
return __readfsdword(Offset);
}

// CHECK-I386-LABEL: define i32 @test__readfsdword(i32 %Offset){{.*}}{
// CHECK-I386-LABEL: define i32 @test__readfsdword(i32 %Offset)
// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i32 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i32, i32 addrspace(257)* [[PTR]], align 4
// CHECK-I386: ret i32 [[VALUE:%[0-9]+]]
// CHECK-I386: }

long long test__readfsqword(unsigned long Offset) {
return __readfsqword(Offset);
}
// CHECK-I386-LABEL: define i64 @test__readfsqword(i32 %Offset)
// CHECK-I386: [[PTR:%[0-9]+]] = inttoptr i32 %Offset to i64 addrspace(257)*
// CHECK-I386: [[VALUE:%[0-9]+]] = load volatile i64, i64 addrspace(257)* [[PTR]], align 8
// CHECK-I386: ret i64 [[VALUE:%[0-9]+]]
#endif

__int64 test__emul(int a, int b) {
Expand All @@ -36,6 +58,43 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) {
// CHECK: ret i64 [[RES]]

#if defined(__x86_64__)

char test__readgsbyte(unsigned long Offset) {
return __readgsbyte(Offset);
}
// CHECK-X64-LABEL: define i8 @test__readgsbyte(i32 %Offset)
// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i8 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i8, i8 addrspace(256)* [[PTR]], align 1
// CHECK-X64: ret i8 [[VALUE:%[0-9]+]]

short test__readgsword(unsigned long Offset) {
return __readgsword(Offset);
}
// CHECK-X64-LABEL: define i16 @test__readgsword(i32 %Offset)
// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i16 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i16, i16 addrspace(256)* [[PTR]], align 2
// CHECK-X64: ret i16 [[VALUE:%[0-9]+]]

long test__readgsdword(unsigned long Offset) {
return __readgsdword(Offset);
}
// CHECK-X64-LABEL: define i32 @test__readgsdword(i32 %Offset)
// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i32 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i32, i32 addrspace(256)* [[PTR]], align 4
// CHECK-X64: ret i32 [[VALUE:%[0-9]+]]

long long test__readgsqword(unsigned long Offset) {
return __readgsqword(Offset);
}
// CHECK-X64-LABEL: define i64 @test__readgsqword(i32 %Offset)
// CHECK-X64: [[ZEXT:%[0-9]+]] = zext i32 %Offset to i64
// CHECK-X64: [[PTR:%[0-9]+]] = inttoptr i64 [[ZEXT]] to i64 addrspace(256)*
// CHECK-X64: [[VALUE:%[0-9]+]] = load volatile i64, i64 addrspace(256)* [[PTR]], align 8
// CHECK-X64: ret i64 [[VALUE:%[0-9]+]]

__int64 test__mulh(__int64 a, __int64 b) {
return __mulh(a, b);
}
Expand Down

0 comments on commit 043f402

Please sign in to comment.