Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -1741,6 +1741,25 @@ Builder.CreateMemSet(Dest, ByteVal, SizeVal, false); return RValue::get(Dest.getPointer()); } + case Builtin::BI__builtin_wmemcmp: { + // The MSVC runtime library does not provide a definition of wmemcmp, so we + // need to implement __builtin_wmemcmp using memcmp. + if (!getTarget().getTriple().isOSMSVCRT()) + break; + llvm::Constant *Memcmp = CGM.CreateRuntimeFunction( + llvm::FunctionType::get(IntTy, {Int8PtrTy, Int8PtrTy, SizeTy}, + /*isVarArg=*/false), + "memcmp"); + llvm::Value *Dst = + Builder.CreateBitOrPointerCast(EmitScalarExpr(E->getArg(0)), Int8PtrTy); + llvm::Value *Src = + Builder.CreateBitOrPointerCast(EmitScalarExpr(E->getArg(1)), Int8PtrTy); + llvm::Value *Size = Builder.CreateMul( + EmitScalarExpr(E->getArg(2)), + llvm::ConstantInt::get( + SizeTy, getContext().getTypeSize(getContext().WCharTy) / 8)); + return RValue::get(Builder.CreateCall(Memcmp, {Dst, Src, Size})); + } case Builtin::BI__builtin_dwarf_cfa: { // The offset in bytes from the first argument to the CFA. // Index: clang/test/CodeGen/wmemcmp.c =================================================================== --- /dev/null +++ clang/test/CodeGen/wmemcmp.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -emit-llvm -o - | FileCheck %s + +typedef __SIZE_TYPE__ size_t; +typedef __WCHAR_TYPE__ wchar_t; + +int wmemcmp_test(const wchar_t *s1, const wchar_t *s2, size_t n) { + // CHECK: [[S1:%.*]] = load + // CHECK: [[S1BC:%.*]] = bitcast i16* [[S1]] to i8* + // CHECK: [[S2:%.*]] = load + // CHECK: [[S2BC:%.*]] = bitcast i16* [[S2]] to i8* + // CHECK: [[N:%.*]] = load + // CHECK: [[N2:%.*]] = mul i64 [[N]], 2 + // CHECK: [[RV:%.*]] = call i32 @memcmp(i8* [[S1BC]], i8* [[S2BC]], i64 [[N2]]) + // CHECK: ret i32 [[RV]] + return __builtin_wmemcmp(s1, s2, n); +}