MSVC compiler intrinsics, need for direction.

sorry this was meant for clang-dev

Hi, I am preparing a patch to add MSVC builtins compiler intrinsics to
clang. (http://msdn.microsoft.com/en-us/library/26td21ds(v=VS.90).aspx)

Things like __noop, __debugbreak, __assume.

I see 2 possible implementations:
1. Put the MSVC intrinsics directly into
clang\include\clang\Basic\Builtins.def and add an argument to specify
if they are MSVC, GCC, ALLNOMS or ALL etc..
This is similar to what we do for keyword tokens.
ex:
BUILTIN(__builtin___noop, "v", "", BUILTIN_MS)

2. Add a new file BuiltinsMSVC.def. Then make the appropriate changes
in the code to handle that: Merging BuiltinsMSVC.def. and
BuiltinsX86.def when triple: win32

I am not sure which is the best option but I am tempted to go with 1.
I would like to have the OK before I start coding that.

Thanks,

I still don't know what's stopping us from adding them unconditionally.

Sebastian

I think it's fine for them to be unconditional. They're all in the implementer's namespace anyway.

  - Doug

I did some research and it will be easier than I thought.
With the exception of __noop and __assume (possibly more), MSVC
intrinsics require a prototype.
So they will be handled like normal functions by clang.

Where does this prototype come from?

  - Doug

#include <intrin.h>

Interesting!

It may still be worth adding these as builtins, unconditionally. A while back, we learned this lesson when we were apparently miscompiling C code like this:

  int* get_int() {
    return (int*)malloc(sizeof(int));
  }

when <stdlib.h> had not been included. This is valid C89: we got an implicit declaration of "malloc" that returned an int. Of course, on platforms with 64-bit pointers and 32-bit ints, this means that we silently lost the upper 32 bits of the malloc'd pointer value! While Clang was technically correct in doing this, GCC does what user's expect because it predeclares all of the builtins. So, we made Clang always declare these builtins, and more of the world's code started to work.

You might consider doing the same for the MSVC builtins. I'll leave that decision to you.

  - Doug

Francois Pichet wrote:

I did some research and it will be easier than I thought.
With the exception of __noop and __assume (possibly more), MSVC
intrinsics require a prototype.
So they will be handled like normal functions by clang.

Where does this prototype come from?

#include <intrin.h>

Just a helpful(?) comment about intrin.h being larger for MSVC10 than for MSVC8 or 9, and that not all of the functions are documented by MSDN (or the Visual Studio help files).

This effort also obviously duplicates some of the work done by Howard Hinnant to define a compiler API for C++0x <atomic>. Do we want several intrinsic functions doing the same thing?

Bo Persson

There is no duplication, Howard's work is related to C++0X library. My
work is related to using clang in a MSVC context without libc++

I was thinking about the _Interlocked intrinsics of MSVC, which could very well be used to implement a large part of <atomic>. Do we need the compiler to provide both an _InterlockedAdd8 and an __atomic_fetch_add_seq_cst? Or could one be implemented as an inline function calling the other?

Just asking.

Bo Persson

The MSVC intrinsics appear to me to be a very small subset of what is needed for both C++0X and C1X. Some of them (like _InterlockedCompareExchange) have subtly different semantics compared to the similarly named C++0X/C1X function.

-Howard