DragonLace.Net
Home of the GNAT AUX and future DRACO Ada compilers.

The following issue is probably not widely known so I'll explain what it was, what platforms it affected, and how it was solved.

The problem was that you couldn't build GCC to support both Ada and C/C++ with long double support perfectly on x86 FreeBSD and x86 DragonFly platforms. You had to choose which language you wanted to provide correct precision: Ada or C/C++. You couldn't have both correct on these platforms.

The reason is that FreeBSD's floating point unit on the i386 platform rounds long doubles down to 53-bit mantissas. GCC knows that FreeBSD does this on its x386 platform and compensates for it. There is a macro for the GCC configuration files called TARGET_96_ROUND_53_LONG_DOUBLE. The default value for this macro is zero (false), but for x86 FreeBSD (and by inheritance, x86 DragonFly), this value must be true. If you build GCC on x86 FreeBSD with this macro set to zero, the results of run time long double calculations (e.g. add, subtract, square root) will be different than expected.

Unfortunately, if you build GCC on x86 FreeBSD with this macro set to 1 (true), then GNAT will fails some precision tests. As long as the builder doesn't build GCC with both GNAT and C++, he could tailor TARGET_96_ROUND_53_LONG_DOUBLE to one language.

Over time, people asked GNAT-AUX and it's successor GCC-AUX to support more than Ada. Currently they support C++, Fortran, and Objective-C as well as the base C language. It was tailored to Ada, so long double calculations with these compilers were suspect. How could it be fixed? The same backend was common to both compiler front ends, presented as libbackend.a during the build.

The solution was to first isolate the source file that initializes the FPU. That file is insn-modes.c, which is generated. During the build, that file is now duplicated and edited to produce insn-modes-ada.c, which ignores the value of TARGET_96_ROUND_53_LONG_DOUBLE (the same as if it were set to false). The object file from this source file is now keep out of the libbackend.a library, but passed along separately to each language front end. The Ada front end gets passed the insn-modes-ada.o object file instead.

That's how the new GCC-AUX compiler (based on gcc-4.7.1) maintains precision quality with both GNAT and the C++ front-end simultaneously. This fix is already available in PKGSRC, and soon I hope to submit a new lang/gcc-aux port for FreeBSD. I'll also publish a comprehensive set of testsuite results that cover all languages and several Operating System / CPU combinations (e.g NetBSD, FreeBSD, DragonFly, OpenSolaris with x86 and x86_64 CPUs).

Last edited Fri May 24 16:28:01 2013
© 2010 John Marino | design elements by styleshout | artwork by Arturo Aguirre