GCC with -fno-builtin does not seem to work

笑着哭i 提交于 2019-12-19 02:14:33

问题


I would like to compare the GCC builtin function memcpy versus the one one from libc. However, all iterations of -fno-builtin or -fno-builtin-memcpy seem to be ignored.

//g++ -O3 foo.cpp -S or
//g++ -O3 -fno-builtin foo.cpp -S
#include <string.h>
int main() {
    volatile int n = 1000;
    //int n = 1000;
    float *x = new float[1000];
    float *y = new float[1000];
    memcpy(y,x,sizeof(float)*n);
    //__builtin_memcpy(y,x,sizeof(float)*n);    
}

What I have found is that if n in the source code above is not volatile then it inlines built-in code. However, when n is made volatile then it calls the function __memcpy_chk which is a version of memcpy with buffer overflow checking. If n is volatile and I instead call __builtin_memcpy then it calls memcpy.

So my conclusion so far is that the builtin code is only generated if n is known at compile time and that -fno-builtin is useless. I'm using GCC 4.8.2.

Is -fno-builtin obsolete? Is there a way to make GCC call memcpy from the C library even when n is known at compile time?


回答1:


-fno-builtin and -fno-builtin-memcpy both have the effect you expected with gcc 4.9.1. This is probably just a bug in gcc 4.8.2; this particular combination of options is not widely used. -ffreestanding is a related switch that may have the effect you want with 4.8.2.

Note that the compiler is within its rights to optimize your program down to

int main() { return 0; }

when invoked without -fno-builtin(-memcpy) or -ffreestanding, even when n is volatile, as it can (in principle) prove that the program as a whole either has no observable side effects, or its behavior is undefined. (When n is not volatile, there cannot be UB; the UB happens if n is outside the range [0, 1000] when read, and volatile tells the compiler it can't assume n has the value written to it by the program.)




回答2:


Note: because you're compiling C++ code, I'm not 100% sure if this applies.

The C standard requires all library functions (unless explicitly indicated otherwise) have an address and can be the operand of the & address operator. This is because it allows some/most functions to be implemented as a functional macro, but should still behave like an actual variable/function in certain cases. To avoid the macro version of it, you just need something between the memcpy token and the ( token (as @Zach pointed out, whitespace is insufficient):

(memcpy)(y, x, ...)

This forces the use of the actual function, which should avoid any sort of builtin macro definition.


It's also possible (read: likely) that the -O3 optimization scans for certain function calls (such as memcpy) and replaces them with builtin calls, regardless of -fno-builtin.




回答3:


Most likely part of your problem is with glibc, not gcc. You didn't specify, but you are probably using Ubuntu, which defines -D_FORTIFY_SOURCE=2 by default. This prompts the glibc headers to provide an inline definition of memcpy that forwards to __memcpy_chk.



来源:https://stackoverflow.com/questions/25272576/gcc-with-fno-builtin-does-not-seem-to-work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!