I have some C code
#include<stdio.h>
#include<stdint.h>
int32_t abs(int32_t x) {
int32_t mask = (x >> 31);
printf("mask is %d\n",mask);
return (x + mask) ^ mask;
}
int main(int argc, char *argv[])
{
int32_t i=-5;
printf("%d\n",abs(i));
return 0;
}
and I compile it with GCC.
gcc -O0 -S -masm=intel
The asm code is in https://pastebin.com/4TGpSsdd
Why doesn't gcc call abs function but clang do.
The program doesn't call abs function and
execute code 「printf("mask is %d\\n",mask);」
My gcc version:
gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
Is this a gcc bug?
abs
is a builtin in GCC, but Clang replaces builtins with calls to their respective library functions.
To fix this, you can rename your function (which is recommended; see below for the reasoning) you can compile your code using -fno-builtin-abs
, or you can mark your function as static
.
Here's a quote from the linked page:
The ISO C90 functions
abort
,abs
,acos
, [...] andvsprintf
are all recognized as built-in functions unless-fno-builtin
is specified (or-fno-builtin- function
is specified for an individual function). All of these functions have corresponding versions prefixed with__builtin_
.
The C standard states that redefining library functions with external is undefined behavior (C11 §7.1.3 1):
All identifiers with external linkage in any of the following subclauses (including the future library directions) and
errno
are always reserved for use as identifiers with external linkage.
If you define abs
as static
, the call will not be removed.
There is a function int abs(int x)
in stdlib.h
.
You need to rename your function.
abs
) are known well to the gcc compiler. They are called built-ins. So compiler knows what this function does and in many cases it does not have to call it.If you rename it - it will genrate the call with the -O0 https://godbolt.org/z/dLg26U
if you want to have it called if you enable optimizations you need to tell the compiler to do not inline it. https://godbolt.org/z/aHaEik
int32_t __attribute__((noinline)) myabs(int32_t x) {
Is this a gcc bug?
No.
abs
is a function defined in the C standard, it's prototype is provided as int abs (int)
by #include <stdlib.h>
.
However, even without including that header, gcc has build-in knowledge about abs
and knows what it is supposed to do. This applies to hosted C, which most users are using.
In non-hosted C however, the compiler must not make any assumptions wrt the semantics of functions declared in the standard headers. In gcc, you get non-hested resp. freestanding by -freestanding
.
In addition, even without optimization turned on ( -O0
), gcc will fold constants. This is because in
int x = 1 + 2;
you cannot do the initialization at run-time for x
in static storage – as opposed to C++ which could initialize that at run-time in principle. In you case
abs (-5)
is folded to 5
.
As you very likely do not want to use -ffreestanding
, you can use -fno-builtin-abs
to take away built-in knowledge about abs
, same for many other functions. Even with -fno-builtin-abs
option, you can use __builtin_abs
in your code if you prefer the optimized version of absolute value computation and no libcall to libc.a
/ libc.so
.
Addendum ad freestanding due to a comment: C99 §4 Conformance, says:
- The two forms of conforming implementation are hosted and freestanding. A conforming hosted implementation shall accept any strictly conforming program. A conforming freestanding implementation shall accept any strictly conforming program that does not use complex types and in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers
<float.h>
,<iso646.h>
,<limits.h>
,<stdarg.h>
,<stdbool.h>
,<stddef.h>
, and<stdint.h>
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.