How GCC handles built-in function

There are roughly two kinds of built-ins: the ones which correspond to standard library functions (malloc, printf and strcpy are all treated as built-ins by default), and the ones which don't have a counterpart in the standard library - think of __builtin_expect, __builtin_prefetch, etc.

The first kind of built-ins are there to enable the compiler to emit optimised code in place of the corresponding calls. Knowing the internal semantics of each of the calls from the standard library, the compiler can decide to either emit a call to the function that resides in the library, or emit a custom-generated piece of code in its place, so that the original semantics are preserved and the code runs better.

The second kind of built-ins (also called "intrinsics") enable tricks and optimisations which are hardly achievable with a static piece of code that resides in a library. They may translate to giving hints to the CPU (__builtin_prefetch, __builtin_expect), or enhancing the C language with better compile-time introspection (__builtin_constant_p, __builtin_types_compatible_p), or providing a simpler, platform-independent interface to some architecture-specific instructions (__builtin_ffs, __builtin_popcount).


What is the difference between a library function and an build-in function?

A built-in function is one that the compiler has some knowledge of directly inside the compiler itself. A library function is simply one defined in a library. A built-in function and a library function of the same name may both exist, so for the rest of your questions, I will treat "library function" as "library function that is not a built-in function".

Is there something a build-in function can do but a library function cannot?

Yes. A built-in function may choose, for example, not to evaluate its arguments:

int main() {
  int i = 0;
  __builtin_constant_p (++i); // checks whether ++i is a constant expression
                              // does not evaluate ++i
  return i; // returns 0
}

This is because a built-in function can be transformed by the compiler into something else, that does not actually need to contain any function call.

Can I write a library function that performs the same task as the build in function printf?

There is some built-in knowledge of printf, but for the most part, this is perfectly doable. Look up how to use <stdarg.h>.

How can I tell the type of the input parameters (%f, float or double)?

You have to trust the caller to let the format string match the remaining arguments; you cannot detect something like passing an int when the format string expects a double. But you don't need to handle the difference between float and double, because it's impossible to pass a float to printf: it will be converted to double (regardless of the format string) before printf sees it. The requirements of printf have been carefully made to avoid any need for any compiler magic.

Machine instructions of GCC build-in functions are not stored in a library, right?

Calls to built-in functions are transformed at compile time, but that transformation may be simply result in a call to a library function of the same name.

Where are they?

If the transformation is done at compile time, there are no machine instructions. The call is transformed into different code, and that code is then compiled to produce machine instructions. If the result is a call to a library function, the machine instructions for that library function are part of the library.

When doing linking, how can you control where to put these build-in function codes?

I don't understand what you mean here. A call to a built-in function is transformed at compile time to different code, and that different code is then compiled as part of the function containing the call. It will be put wherever the rest of the code of that containing function will be put.

Why sometimes I can error messages like "undefined reference to __builtin_stdarg_start" when doing linking

There is no built-in function __builtin_stdarg_start, despite the __builtin prefix, so this is treated as a call to a library function. And there is no library function __builtin_stdarg_start either, so the linker detects this as an error.

There used to be a built-in function __builtin_stdarg_start, but it was removed years ago, and code never should have been using it in the first place.

gcc -c main.c, nm shows that there is no symbol printf in main.o, (only main(T) and puts(U)) , why?

That's because printf exists both as a built-in function and as a library function. The built-in function usually simply calls the library function, but sometimes it is possible to do better, including in your example. In this case, the built-in function printf can give the correct result without calling the library function printf.

Tags:

C++

C

Gcc