How to use compiler builtin functions without Stan

2020-07-24 15:39发布

问题:

I know that some functions like sin cos min max memcpy may be treated not as normal functions but may be replaced by built-in functions (which may be more optimal than merely inline function calls, when the replacement is (an) actual processor instruction(s), such as directly calling the FSIN instruction for standard sin function when compiled for an x86 with a floating point unit).

The question I would like to use power of built-in functions (in C/C++ mostly in mingw/gcc maybe other compiler) but I do not want to link to libc, the Standard C Library).

  • Is it possible to use builtins with not linking to libc?

  • Are they any command line flags needed to optimize those symbols as a built-ins?

    (Related to previous, but rephrased)

  • Will they be automatically recognized by name, or are compiler flag(s) necessary to enable usage of built-ins?

回答1:

Lets say you wanted to replace the function cos, all you have to do is replace every occurance of cos in your code with __builtin_cos. The same goes for any other function that you can replace with the compiler's version. Just prepend __builtin_ to the name.

For more information consult the gcc manual.



回答2:

@randomusername has already explained the usage of the __builtin_ prefix for many common Standard C Library functions. I recommend using #define to make the change, while keeping your code clean.

#include <math.h>

#define  cos   __builtin_cos
#define  sin   __builtin_sin
#define  printf __builtin_printf

...
   printf("Distance is %f\n", cos(M_PI/4.0) * 7);
...

No Standard C Library

Now to not use the Standard C Library, which means not linking to it, or including the typical startup and exit code stubs, well, with GCC that is possible with the -nostdlib which is equivalent to -nostartfiles and -nodefaultlibs.

The issue is that you then have to replace all the library functions you would normally use, including system calls (or their wrappers / macros from glibc) for any kernel based functions.

I don't know of a portable or robust method that works across processors or even necessarily different families (sysenter vs. syscall (instruction) vs. int 0x80 for various 32 and 64-bit x86 processors). There is issues with ELF Auxiliary Vectors (Elf32_auxv_t) and vDSO (virtual ELF dynamic shared object) that may be possible to address and create a portable solution, I don't know.

Entry Point

I believe all GCC environments use the same default entry point, which is the label/function _start. This is normally included in the "Startup files" and then calls the traditional C/C++ entry point of main. So you would need to replace it with a minimal stub of your own (which can be in C).

Program termination

I don't know how to replace _exit(rc) or similar function required to correct terminate the program, in a portable fashion. For example in a Linux environment it needs to make a system call to the kernel function SYS_exit (aka __NR_exit or sys_exit)

void _start(void) {
    int rc;
    /* Get command line arguments if necessary */
    rc = main(0, NULL);
    your_exit_replacement(rc);
}

Alternatives

Normally user processes i.e. application programs, as opposed to Operating System kernels or drivers, accept the overhead of linking the Startup Files and the necessary overhead to enable dynamic linking to the Startard C Library, as memory is considered cheap and readily available that for any real (actually does something) application the memory saving is not worthwhile. In embedded domain, where it is not as acceptable to just assume plenty of memory is available, the alternative is the use a minimal libc replacement. For Linux there are several available (e.g. musl, uClibc, dietlibc), I don't know if there is one available for mingw or Windows-compatible open source replacements (ReactOS, and Wine).

Further

For further information, from a Linux platform point of view, there is a nice introduction "Hello from a libc-free world!" Part 1 and Part 2 by Jessica McKellar blogging at Oracle. There are also a number of related questions, and some (partial in some cases) answers here at stackoverflow about using -nostdlib in various circumstances.

Where to go from here depends on your goals: education, embedded, tiny program (Linux ELF executable) or Windows PE executable competitions.

Microsoft Windows

There are various articles for a Microsoft Windows environment dealing with .COM and .EXE executables, and Windows PE but using Microsoft's Visual Studio environment or assembly typically. The "classics" are Matt Pietrek's Under the Hood column "Reduce EXE and DLL Size with LIBCTINY.LIB" (January 2001 issue of MSDN Magazine) and "Remove Fatty Deposits from Your Applications Using Our 32-Bit Liposuction Tools" from October 1996 Microsoft Systems Journal. Another article, but I haven't read myself, that appears to have include explanations is "Reducing Executable Size".