Index: include/clang/Basic/Builtins.def =================================================================== --- include/clang/Basic/Builtins.def +++ include/clang/Basic/Builtins.def @@ -683,9 +683,12 @@ LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES) // C99 library functions // C99 stdlib.h Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -858,6 +858,9 @@ return RValue::get(nullptr); } + case Builtin::BI_InterlockedExchange: + case Builtin::BI_InterlockedExchangePointer: + case Builtin::BI_InterlockedCompareExchangePointer: case Builtin::BI__sync_fetch_and_add: case Builtin::BI__sync_fetch_and_sub: case Builtin::BI__sync_fetch_and_or: Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -132,6 +132,22 @@ return true; ICEArguments &= ~(1 << ArgNo); } + + switch (BuiltinID) { + case Builtin::BI_InterlockedExchange: + case Builtin::BI_InterlockedExchangePointer: + BuiltinID = Builtin::BI__sync_lock_test_and_set; + break; + case Builtin::BI_InterlockedCompareExchangePointer: + BuiltinID = Builtin::BI__sync_val_compare_and_swap; + + assert(TheCall->getNumArgs() == 3); + Expr *Arg1 = TheCall->getArg(1), *Arg2 = TheCall->getArg(2); + TheCall->setArg(1, Arg2); + TheCall->setArg(2, Arg1); + + break; + } switch (BuiltinID) { case Builtin::BI__builtin___CFStringMakeConstantString: @@ -1471,6 +1487,7 @@ BuiltinIndex = 9; break; + case Builtin::BI_InterlockedCompareExchangePointer: case Builtin::BI__sync_val_compare_and_swap: case Builtin::BI__sync_val_compare_and_swap_1: case Builtin::BI__sync_val_compare_and_swap_2: @@ -1492,6 +1509,8 @@ ResultType = Context.BoolTy; break; + case Builtin::BI_InterlockedExchange: + case Builtin::BI_InterlockedExchangePointer: case Builtin::BI__sync_lock_test_and_set: case Builtin::BI__sync_lock_test_and_set_1: case Builtin::BI__sync_lock_test_and_set_2: Index: test/CodeGen/ms-intrinsics.c =================================================================== --- /dev/null +++ test/CodeGen/ms-intrinsics.c @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -triple i686--windows -fms-compatibility -Oz -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple thumbv7--windows -fms-compatibility -Oz -emit-llvm %s -o - | FileCheck %s + +void *test_InterlockedExchangePointer(void * volatile *Target, void *Value) { + return _InterlockedExchangePointer(Target, Value); +} + +// CHECK: define{{.*}}i8* @test_InterlockedExchangePointer(i8** %Target, i8* %Value){{.*}}{ +// CHECK: entry: +// CHECK: %0 = bitcast i8** %Target to i32* +// CHECK: %1 = ptrtoint i8* %Value to i32 +// CHECK: %2 = atomicrmw xchg i32* %0, i32 %1 seq_cst +// CHECK: %3 = inttoptr i32 %2 to i8* +// CHECK: ret i8* %3 +// CHECK: } + +void *test_InterlockedCompareExchangePointer(void * volatile *Destination, + void *Exchange, void *Comperand) { + return _InterlockedCompareExchangePointer(Destination, Exchange, Comperand); +} + +// CHECK: define{{.*}}i8* @test_InterlockedCompareExchangePointer(i8** %Destination, i8* %Exchange, i8* %Comperand){{.*}}{ +// CHECK: entry: +// CHECK: %0 = bitcast i8** %Destination to i32* +// CHECK: %1 = ptrtoint i8* %Comperand to i32 +// CHECK: %2 = ptrtoint i8* %Exchange to i32 +// CHECK: %3 = cmpxchg i32* %0, i32 %1, i32 %2 seq_cst seq_cst +// CHECK: %4 = inttoptr i32 %3 to i8* +// CHECK: ret i8* %4 +// CHECK: } + +long test_InterlockedExchange(long *Target, long Value) { + return _InterlockedExchange(Target, Value); +} + +// CHECK: define{{.*}}i32 @test_InterlockedExchange(i32* %Target, i32 %Value){{.*}}{ +// CHECK: entry: +// CHECK: %0 = atomicrmw xchg i32* %Target, i32 %Value seq_cst +// CHECK: ret i32 %0 +// CHECK: }