From 1deab387170a0877485e9aca7461acac79b33be3 Mon Sep 17 00:00:00 2001 From: Albert Gutowski Date: Fri, 14 Oct 2016 17:33:05 +0000 Subject: [PATCH] Implement __stosb intrinsic as a volatile memset Summary: We need `__stosb` to be an intrinsic, because SecureZeroMemory function uses it without including intrin.h. Implementing it as a volatile memset is not consistent with MSDN specification, but it gives us target-independent IR while keeping the most important properties of `__stosb`. Reviewers: rnk, hans, thakis, majnemer Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D25334 llvm-svn: 284253 --- clang/include/clang/Basic/BuiltinsX86.def | 2 ++ clang/lib/CodeGen/CGBuiltin.cpp | 5 +++++ clang/lib/Headers/intrin.h | 5 ----- clang/test/CodeGen/ms-intrinsics.c | 16 ++++++++++++++++ clang/test/Headers/ms-intrin.cpp | 1 - 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Basic/BuiltinsX86.def b/clang/include/clang/Basic/BuiltinsX86.def index 06c590a..8e3fa3d 100644 --- a/clang/include/clang/Basic/BuiltinsX86.def +++ b/clang/include/clang/Basic/BuiltinsX86.def @@ -2041,6 +2041,8 @@ TARGET_HEADER_BUILTIN(__emulu, "ULLiUiUi", "nh", "intrin.h", ALL_MS_LANGUAGES, " TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__stosb, "vUc*Ucz", "nh", "intrin.h", ALL_MS_LANGUAGES, "") + #undef BUILTIN #undef TARGET_BUILTIN #undef TARGET_HEADER_BUILTIN diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index bfec53a..8bb9a46 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -7770,6 +7770,11 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, Value *F = CGM.getIntrinsic(Intrinsic::addressofreturnaddress); return Builder.CreateCall(F); } + case X86::BI__stosb: { + // We treat __stosb as a volatile memset - it may not generate "rep stosb" + // instruction, but it will create a memset that won't be optimized away. + return Builder.CreateMemSet(Ops[0], Ops[1], Ops[2], 1, true); + } } } diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index fe42d08..76cbb9a 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -1024,11 +1024,6 @@ __movsw(unsigned short *__dst, unsigned short const *__src, size_t __n) { : "%edi", "%esi", "%ecx"); } static __inline__ void __DEFAULT_FN_ATTRS -__stosb(unsigned char *__dst, unsigned char __x, size_t __n) { - __asm__("rep stosb" : : "D"(__dst), "a"(__x), "c"(__n) - : "%edi", "%ecx"); -} -static __inline__ void __DEFAULT_FN_ATTRS __stosd(unsigned long *__dst, unsigned long __x, size_t __n) { __asm__("rep stosl" : : "D"(__dst), "a"(__x), "c"(__n) : "%edi", "%ecx"); diff --git a/clang/test/CodeGen/ms-intrinsics.c b/clang/test/CodeGen/ms-intrinsics.c index 0da3442..25eae44 100644 --- a/clang/test/CodeGen/ms-intrinsics.c +++ b/clang/test/CodeGen/ms-intrinsics.c @@ -14,6 +14,22 @@ typedef __SIZE_TYPE__ size_t; #include +#if defined(__i386__) || defined(__x86_64__) +void test__stosb(unsigned char *Dest, unsigned char Data, size_t Count) { + return __stosb(Dest, Data, Count); +} + +// CHECK-I386: define{{.*}}void @test__stosb +// CHECK-I386: tail call void @llvm.memset.p0i8.i32(i8* %Dest, i8 %Data, i32 %Count, i32 1, i1 true) +// CHECK-I386: ret void +// CHECK-I386: } + +// CHECK-X64: define{{.*}}void @test__stosb +// CHECK-X64: tail call void @llvm.memset.p0i8.i64(i8* %Dest, i8 %Data, i64 %Count, i32 1, i1 true) +// CHECK-X64: ret void +// CHECK-X64: } +#endif + void *test_ReturnAddress() { return _ReturnAddress(); } diff --git a/clang/test/Headers/ms-intrin.cpp b/clang/test/Headers/ms-intrin.cpp index 4d6803a..d410b1d 100644 --- a/clang/test/Headers/ms-intrin.cpp +++ b/clang/test/Headers/ms-intrin.cpp @@ -38,7 +38,6 @@ void f() { __movsd(0, 0, 0); __movsw(0, 0, 0); - __stosb(0, 0, 0); __stosd(0, 0, 0); __stosw(0, 0, 0); -- 2.7.4