GCC如何处理内置函数

时间:2020-12-06 04:19:02

I have trouble understanding GCC built-in functions, and feel very confused.

我理解GCC内置函数有困难,感觉很困惑。

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

    库函数和内置函数的区别是什么?

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

    有什么内置函数可以做而库函数不能做的吗?

  • Can I write a library function that performs the same task as the built-in function printf? How can I tell the type of the input parameters (%f, float or double)?

    我可以编写一个库函数来执行与内置函数printf相同的任务吗?如何判断输入参数的类型(%f、float或double)?

  • Machine instructions of GCC built-in functions are not stored in a library, right? Where are they?

    GCC内置函数的机器指令不存储在库中,对吗?他们在哪儿?

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

    在进行链接时,如何控制将这些内置函数代码放在哪里?

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

    为什么有时候我可以在链接的时候出错,比如“undefined引用__builtin_stdarg_start”?

    // main.c
    #include <stdio.h>
    int main(void) {
      printf("hello world!\n");
      return 0;
    }
    

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

    gcc - c主要。c, nm表示不存在主符号printf。o(只有main(T)和put (U)),为什么?

2 个解决方案

#1


18  

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".

内置函数是编译器本身就知道的函数。库函数就是库中定义的函数。一个内置函数和一个同名的库函数都可能存在,所以对于您的其他问题,我将把“library function”视为“library 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?

我可以编写一个库函数来执行与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>.

printf有一些内置的知识,但在大多数情况下,这是完全可行的。查找如何使用

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

如何判断输入参数的类型(%f、float或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.

您必须信任调用者,使格式字符串与其余参数匹配;当格式字符串需要双精度符时,您不能检测到像传递int这样的东西。但是您不需要处理float和double之间的区别,因为不可能将float传递给printf:在printf看到它之前,它将被转换为double(不管格式字符串是什么)。printf的要求是经过仔细设计的,以避免任何编译器魔法的需要。

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

GCC内置函数的机器指令不存储在库中,对吗?

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

为什么有时候我可以在链接的时候出错,比如“undefined引用__builtin_stdarg_start”?

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.

尽管有__builtin_stdarg_start前缀,但是没有内置函数__builtin_stdarg_start,因此这被视为对库函数的调用。而且也没有__builtin_stdarg_start库函数,因此链接器将其检测为错误。

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.

以前有一个内置函数__builtin_stdarg_start,但是它在多年前就被删除了,而且代码本来就不应该使用它。

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

gcc - c主要。c, nm表示不存在主符号printf。o(只有main(T)和put (U)),为什么?

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.

这是因为printf既作为一个内置函数,也作为一个库函数存在。内置函数通常只调用库函数,但有时可以做得更好,包括在您的示例中。在这种情况下,内置函数printf可以在不调用库函数printf的情况下给出正确的结果。

#2


6  

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.

大致有两种内置函数:与标准库函数对应的函数(malloc、printf和strcpy默认都被视为内置函数),以及标准库中没有对应函数的函数——如__builtin_expect、__builtin_prefetch等。

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).

第二种内嵌(也称为“intrinsic”)支持技巧和优化,这在库中的静态代码块中很难实现。它们可以转换为向CPU (__builtin_prefetch, __builtin_expect)提供提示,或者使用更好的编译时内省(__builtin_constant_p、__builtin_types_compatible_p)增强C语言,或者为某些特定于体系结构的指令(__builtin_ffs、__builtin_popcount)提供更简单的、独立于平台的接口。

#1


18  

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".

内置函数是编译器本身就知道的函数。库函数就是库中定义的函数。一个内置函数和一个同名的库函数都可能存在,所以对于您的其他问题,我将把“library function”视为“library 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?

我可以编写一个库函数来执行与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>.

printf有一些内置的知识,但在大多数情况下,这是完全可行的。查找如何使用

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

如何判断输入参数的类型(%f、float或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.

您必须信任调用者,使格式字符串与其余参数匹配;当格式字符串需要双精度符时,您不能检测到像传递int这样的东西。但是您不需要处理float和double之间的区别,因为不可能将float传递给printf:在printf看到它之前,它将被转换为double(不管格式字符串是什么)。printf的要求是经过仔细设计的,以避免任何编译器魔法的需要。

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

GCC内置函数的机器指令不存储在库中,对吗?

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

为什么有时候我可以在链接的时候出错,比如“undefined引用__builtin_stdarg_start”?

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.

尽管有__builtin_stdarg_start前缀,但是没有内置函数__builtin_stdarg_start,因此这被视为对库函数的调用。而且也没有__builtin_stdarg_start库函数,因此链接器将其检测为错误。

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.

以前有一个内置函数__builtin_stdarg_start,但是它在多年前就被删除了,而且代码本来就不应该使用它。

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

gcc - c主要。c, nm表示不存在主符号printf。o(只有main(T)和put (U)),为什么?

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.

这是因为printf既作为一个内置函数,也作为一个库函数存在。内置函数通常只调用库函数,但有时可以做得更好,包括在您的示例中。在这种情况下,内置函数printf可以在不调用库函数printf的情况下给出正确的结果。

#2


6  

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.

大致有两种内置函数:与标准库函数对应的函数(malloc、printf和strcpy默认都被视为内置函数),以及标准库中没有对应函数的函数——如__builtin_expect、__builtin_prefetch等。

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).

第二种内嵌(也称为“intrinsic”)支持技巧和优化,这在库中的静态代码块中很难实现。它们可以转换为向CPU (__builtin_prefetch, __builtin_expect)提供提示,或者使用更好的编译时内省(__builtin_constant_p、__builtin_types_compatible_p)增强C语言,或者为某些特定于体系结构的指令(__builtin_ffs、__builtin_popcount)提供更简单的、独立于平台的接口。