Compiler builtins/included headers
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Compiler builtins/included headers
Hi,
I've been filling in some of the edges of my C library, and I realized that many architecture-specific headers (like stdint.h, float.h) are not defined in the C library (at least not glibc), and are instead packaged with the compiler, and use compiler builtin macros for portability. Is it standard practice to not write these headers and leave them to the C compiler? Are these headers guaranteed to exist for every compiler, or are they a GNU extension?
Also, I've been working on my math library, and while I finished C89 support and my functions have very high accuracy, they are extremely slow in comparison to the compiler builtins when I test them under Linux. I'm going to be using CLang and GCC pretty much exclusively for building my OS, so is it okay to use the builtins in my OS? (I'm checking for __GNUC__ of course) Are there GPL issues with this?
Thanks,
Nick Johnson
I've been filling in some of the edges of my C library, and I realized that many architecture-specific headers (like stdint.h, float.h) are not defined in the C library (at least not glibc), and are instead packaged with the compiler, and use compiler builtin macros for portability. Is it standard practice to not write these headers and leave them to the C compiler? Are these headers guaranteed to exist for every compiler, or are they a GNU extension?
Also, I've been working on my math library, and while I finished C89 support and my functions have very high accuracy, they are extremely slow in comparison to the compiler builtins when I test them under Linux. I'm going to be using CLang and GCC pretty much exclusively for building my OS, so is it okay to use the builtins in my OS? (I'm checking for __GNUC__ of course) Are there GPL issues with this?
Thanks,
Nick Johnson
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Re: Compiler builtins/included headers
I'm also thinking about this because of complex.h: the complex type is sort of opaque (i.e. compiler-dependent), so it seems like I'd need at least the builtins to extract the real and imaginary components as floating point values and to put them back together again.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Compiler builtins/included headers
You have two choices here really: you can use stdint.h and other existing stuff and build your C library on top of that, or you can write your own headers in such a fashion that you can point it to compiler internals when needed.
Using compiler internals indiscriminately will make you very dependent on the compiler in question, and will get you in serious problems the moment GCC isn't the de-facto compiler anymore (or you need a different compiler for any reason).
Using compiler internals indiscriminately will make you very dependent on the compiler in question, and will get you in serious problems the moment GCC isn't the de-facto compiler anymore (or you need a different compiler for any reason).
-
- Member
- Posts: 255
- Joined: Tue Jun 15, 2010 9:27 am
- Location: Flyover State, United States
- Contact:
Re: Compiler builtins/included headers
My solution was to use compiler built-ins for the most common compilers (GCC and MSVC) if they're being used to compile them, and otherwise to provide a portable fallback definition if they're absent.
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Re: Compiler builtins/included headers
How exactly would you do that? It seems like the only method is #include_next, but I don't want to stop using -pedantic.Combuster wrote:... or you can write your own headers in such a fashion that you can point it to compiler internals when needed.
Well, I'm using clang (which is compatible with GCC for the relevant builtins and headers), and I'm pretty sure that one of them is going to be the de-facto compiler for quite a while to come, not to mention that I'm almost definitely going to be using clang as my system's compiler. That said, I would like to keep portability if possible. It seems almost as if I'm screwed either way, since using the compiler's headers makes me dependent on the compiler, but writing my own headers makes me dependent on the architecture _and_ the compiler's native types.Combuster wrote:Using compiler internals indiscriminately will make you very dependent on the compiler in question, and will get you in serious problems the moment GCC isn't the de-facto compiler anymore (or you need a different compiler for any reason).
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Compiler builtins/included headers
There be design patterns for that - Shameless plug.
Re: Compiler builtins/included headers
So #pragma GCC system_header is your friend.NickJohnson wrote:How exactly would you do that? It seems like the only method is #include_next, but I don't want to stop using -pedantic.Combuster wrote:... or you can write your own headers in such a fashion that you can point it to compiler internals when needed.
-
- Member
- Posts: 255
- Joined: Tue Jun 15, 2010 9:27 am
- Location: Flyover State, United States
- Contact:
Re: Compiler builtins/included headers
Here is a great site: http://predef.sourceforge.net/
You can use pre-defined compiler macros to determine which compiler, and even which architecture, you are compiling for. Make sure you are careful about it though. So let's say you wanted to define the macro va_start. I do it something like this in my subset of the C library:
You can use pre-defined compiler macros to determine which compiler, and even which architecture, you are compiling for. Make sure you are careful about it though. So let's say you wanted to define the macro va_start. I do it something like this in my subset of the C library:
Code: Select all
#ifdef __GNUC__
typedef __builtin_va_list va_list;
#define va_start(v,l) __builtin_va_start(v,l)
#elif defined(_MSC_VER)
/* VC-specific stuff here */
#else
/* fallback implementation here */
#endif
Re: Compiler builtins/included headers
The "freestanding" headers (i.e., those containing only defines and typedefs, but not coming with any actual code attached - <limits.h>, <stddef.h>, <stdint.h> etc.) are technically very much depending on the compiler (e.g. the width of the various integer types), and not depending on the rest of the standard library at all. That is why they are defined by GCC, not glibc.
PDCLib uses a central configuration header - the one Combuster linked to - to determine all the various settings required in the other headers. (As opposed to glibc, which scatters compiler-specific #ifdefs all over the place.)
If you are interested as how I go on from there, the "workhorse" header doing most of the work on those settings with regards to <limit.h> and <stdint.h> is <_PDCLIB_int.h>. The <stdint.h> header itself is, by comparison, rather brainless, as it only "forwards" the standard defines and typedefs to the internal ones.
However, as it stands, this concept will result in a compiler-specific library. A different compiler for the same platform that does things somewhat differently would require its own configuration header, and its own library binary. Since the main target for PDCLib is the OSDev community, I didn't think much about multi-compiler setups yet.
However, look at Tosi's hint at compiler-specific predefines (__GNUC__ and _MSC_VER spring to mind, but every compiler has one of these uniquely identifying it). When you use that, find the places in PDCLib where <_PDCLIB_config.h> is included, you can create up a multi-CPU library header setup along the lines of this:
You would still need to have seperate library binaries for each of the compilers involved (or you would end up with differences in what the headers declare and what the binaries contain).
Thanks for the plug, but I fear what I did for PDCLib so far is only one half of what NickJohnson is looking for.Combuster wrote:There be design patterns for that - Shameless plug.NickJohnson wrote:How exactly would you do that? It seems like the only method is #include_next, but I don't want to stop using -pedantic.Combuster wrote:... or you can write your own headers in such a fashion that you can point it to compiler internals when needed.
PDCLib uses a central configuration header - the one Combuster linked to - to determine all the various settings required in the other headers. (As opposed to glibc, which scatters compiler-specific #ifdefs all over the place.)
If you are interested as how I go on from there, the "workhorse" header doing most of the work on those settings with regards to <limit.h> and <stdint.h> is <_PDCLIB_int.h>. The <stdint.h> header itself is, by comparison, rather brainless, as it only "forwards" the standard defines and typedefs to the internal ones.
However, as it stands, this concept will result in a compiler-specific library. A different compiler for the same platform that does things somewhat differently would require its own configuration header, and its own library binary. Since the main target for PDCLib is the OSDev community, I didn't think much about multi-compiler setups yet.
However, look at Tosi's hint at compiler-specific predefines (__GNUC__ and _MSC_VER spring to mind, but every compiler has one of these uniquely identifying it). When you use that, find the places in PDCLib where <_PDCLIB_config.h> is included, you can create up a multi-CPU library header setup along the lines of this:
Code: Select all
#if defined( __GNUC__ )
#if __GNUC__ <= 3
#include <gcc_old/_PDCLIB_config.h>
#elif __GNUC__ > 3
#include <gcc_new/_PDCLIB_config.h>
#else
#error "Strange value for __GNUC__"
#endif
#elif defined( _MSC_VER )
#if _MSC_VER < 1600
#include <msvc_old/_PDCLIB_config.h>
#elif _MSC_VER >= 1600
#include <msvc_new/_PDCLIB_config.h>
#else
#error "Strange value for _MSC_VER"
#endif
#endif
Every good solution is obvious once you've found it.