Compiler builtins/included headers

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Compiler builtins/included headers

Post 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
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Compiler builtins/included headers

Post 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.
User avatar
Combuster
Member
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

Post 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).
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: Compiler builtins/included headers

Post 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.
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Compiler builtins/included headers

Post 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.
User avatar
Combuster
Member
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

Post by Combuster »

There be design patterns for that - Shameless plug.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Fanael
Member
Member
Posts: 38
Joined: Fri Oct 16, 2009 9:20 am

Re: Compiler builtins/included headers

Post 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.
Tosi
Member
Member
Posts: 255
Joined: Tue Jun 15, 2010 9:27 am
Location: Flyover State, United States
Contact:

Re: Compiler builtins/included headers

Post 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
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Compiler builtins/included headers

Post 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).
Every good solution is obvious once you've found it.
Post Reply