[Patch] __builtin_expect uses long, not int

Hi folks,

Robert Watson discovered an issue with __builtin_expect() while porting
libdispatch to FreeBSD/amd64. According to the GCC docs,
__builtin_expect looks like this:

long __builtin_expect (long exp, long c);

But currently we use this line in Builtins.def:

BUILTIN(__builtin_expect, "iii" , "nc")

This means the arguments and the return value are of type int. This
breaks libdispatch, because it tries to pass pointers through this
function.

Patch:

Index: include/clang/Basic/Builtins.def

Hi folks,

Robert Watson discovered an issue with __builtin_expect() while porting
libdispatch to FreeBSD/amd64. According to the GCC docs,
__builtin_expect looks like this:

long __builtin_expect (long exp, long c);

But currently we use this line in Builtins.def:

BUILTIN(__builtin_expect, “iii” , “nc”)

This means the arguments and the return value are of type int. This
breaks libdispatch, because it tries to pass pointers through this
function.

Ow, good catch.

Patch:

Index: include/clang/Basic/Builtins.def

— include/clang/Basic/Builtins.def (revision 85650)
+++ include/clang/Basic/Builtins.def (working copy)
@@ -329,7 +329,7 @@
BUILTIN(__builtin___vfprintf_chk, “iPicCa”, “FP:2:”)
BUILTIN(__builtin___vprintf_chk, “iicC*a”, “FP:1:”)

-BUILTIN(__builtin_expect, “iii” , “nc”)
+BUILTIN(__builtin_expect, “LiLiLi”, “nc”)
BUILTIN(__builtin_prefetch, “vvC*.”, “nc”)
BUILTIN(__builtin_abort, “v”, “Fnr”)
BUILTIN(__builtin_trap, “v”, “nr”)

Thank you, committed here:

http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20091026/022975.html

I’ve been thinking about adding some tests to the test suite. Maybe we
could test something along these lines:

ULONG_MAX == __builtin_expect(ULONG_MAX, 1)

Since we avoid executable tests in the test-suite, we’d want to look at the generated IR to make sure it preserves the value of LONG_MAX. However, I settled for something a little simpler:

extern long int bi0;
extern typeof(__builtin_expect(0, 0)) bi0;

  • Doug