Page 1 of 1

Compiler builtins/included headers

Posted: Sat Jan 15, 2011 7:25 pm
by NickJohnson
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

Re: Compiler builtins/included headers

Posted: Sun Jan 16, 2011 9:39 am
by NickJohnson
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.

Re: Compiler builtins/included headers

Posted: Sun Jan 16, 2011 12:00 pm
by Combuster
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).

Re: Compiler builtins/included headers

Posted: Sun Jan 16, 2011 12:14 pm
by Tosi
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.

Re: Compiler builtins/included headers

Posted: Sun Jan 16, 2011 12:26 pm
by NickJohnson
Combuster wrote:... or you can write your own headers in such a fashion that you can point it to compiler internals when needed.
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: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).
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.

Re: Compiler builtins/included headers

Posted: Sun Jan 16, 2011 1:14 pm
by Combuster
There be design patterns for that - Shameless plug.

Re: Compiler builtins/included headers

Posted: Mon Jan 17, 2011 10:15 am
by Fanael
NickJohnson wrote:
Combuster wrote:... or you can write your own headers in such a fashion that you can point it to compiler internals when needed.
How exactly would you do that? It seems like the only method is #include_next, but I don't want to stop using -pedantic.
So #pragma GCC system_header is your friend.

Re: Compiler builtins/included headers

Posted: Mon Jan 17, 2011 1:55 pm
by Tosi
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:

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

Posted: Tue Jan 18, 2011 3:47 am
by Solar
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.
Combuster wrote:
NickJohnson wrote:
Combuster wrote:... or you can write your own headers in such a fashion that you can point it to compiler internals when needed.
How exactly would you do that? It seems like the only method is #include_next, but I don't want to stop using -pedantic.
There be design patterns for that - Shameless plug.
Thanks for the plug, but I fear what I did for PDCLib so far is only one half of what NickJohnson is looking for.

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