llrint implementation in Cygwin

Brian Dessent brian@dessent.net
Sat Oct 27 11:45:00 GMT 2007


Victor Paesa wrote:

> I downloaded the gcc-3.4.4 Cygwin source package, and I found that (apparently)
> gcc 3.4.4 already had llrint built-in:

A builtin in gcc has a specific meaning, and it does not mean that the
compiler provides a full implementation of that function.  What it means
is that the compiler knows how to optimize certain special cases of that
function, such as it knows it can replace strlen("foo") with 3 because
it can see that foo has length 3 at compile time.  But the key here is
that for all builtins that have the same name as standard C functions,
the compiler assumes that there is a corresponding library
implementation of the function that can always be called as a fallback
if the limited builtin cannot suffice or if there is no chance of any
optimization possible.

[ There are many other types of builtins besides those that
mirror/parallel the standard C library functions.  Some implement
"magic" things like __builtin_expect, __builtin_apply_args, or
__builtin_return_address; some expose processor features directly like
__sync_lock_test_and_set, etc. ]

> $ fgrep -ri llrint gcc-3.4.4
> gcc-3.4.4/gcc/builtins.c:      CASE_MATHFN (BUILT_IN_LLRINT)
> gcc-3.4.4/gcc/builtins.def:DEF_C99_BUILTIN        (BUILT_IN_LLRINT, "llrint",
> BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)

What you see here is the machinery to support llrint as a builtin, but
it's not actually implemented anywhere.  Note that in
builtins.c:expand_builtin(), there is no case statement to handle
BUILT_IN_LLRINT{,F,L} and so the switch falls through to the bottom of
the function which contains:

  /* The switch statement above can drop through to cause the function
     to be called normally.  */
  return expand_call (exp, target, ignore);

This simply means that it punts and calls the library version of the
function, which is exactly what you see below -- except that
Cygwin/newlib does not provide a library version of this function.

> $ cat llrint_test.c
> #include <math.h>
> int main(int argc, char **argv)
> {
>   long long ll;
> 
>   ll = __builtin_llrint(2.34);
> }
> 
> But the compilation failed:
> $ gcc llrint_test.c
> /cygdrive/c/DOCUME~1/Inma/LOCALS~1/Temp/ccyDtvBd.o:llrint_test.c:(.text+0x34):
> undefined reference to `_llrint'
> collect2: ld returned 1 exit status
> 
> Are built-ins disabled in gcc-3.4.4 for Cygwin?

No, they're not disabled, it's just that there's no implementation of
__builtin_llrint in this version of gcc, though there is plumbing for
it.  But even if there were a builtin, it would not be a full
replacement for llrint, because again builtins are meant to mirror the
library implementations in situations where the compiler has a clear
chance of optimizing something away (such as when you call it with a
constant), not replace the library version as a general purpose
implementation.  So even if it did have a __builtin_llrint, you would
not be able to use it any non-trivial manner.

[ Also note that you did not invoke gcc with optimization above, which
I'm pretty sure means it won't even consider using optimized builtins. ]

> Could that be fixed by adding/removing flags to the configure line used
> to build gcc 3.4.4 in Cygwin?

No what needs to be done is add llrint to newlib.  A builtin is not a
suitable replacement.

Brian

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/



More information about the Cygwin mailing list