Technical News from The Portland Group
The New PGC++ Compiler for Linux
C++ was invented by Bjarne Stroustrup more than 25 years ago as a superset to the C language, with the key addition of classes as an advanced data abstraction mechanism. Since then, it has evolved with the addition of templates (allowing template metaprogramming), exception handling, the Standard Template Library (STL), namespaces, and many other features. Recently, the C++11 standard was adopted, providing further enhancements, most notably, the TR1 extensions to the C++ Standard Template Library. C++ has been adopted by many, many software developers in part because it promotes code reuse and hence programming productivity.
The Role of the ABI
One thing that was missing from the C++ specifications was an ABI, an Application Binary Interface. An ABI specifies such things as how to pass arguments from caller to callee procedure, how to lay out and align data in a struct and how to decorate procedure or global variable names. For instance, the X86-64 ABI used for Linux specifies that the first four integer or address arguments are passed in registers %rdi, %rsi, %rdx, %rcx, and that Fortran procedures (by convention) use lower case names with an underscore appended. An ABI is necessary so different compilers and software development tools can generate code that interoperates. Typically, an ABI depends on the processor type and operating system. For instance, the 64-bit X86-64 Windows ABI uses different registers for passing parameters.
When C++ was being developed, there was no thought given to an official ABI. However, there are many C++ features that need support beyond what is provided in a C-oriented ABI. For instance, procedure names need to be mangled; the Standard Template Library constructor routine for the vector class requires that the constructor be instantiated for the appropriate template, and given a unique name that corresponds to that instantiation, such as
std::vector<T1, T2>::vector<unsigned int, std::allocator<unsigned int>> (unsigned long) [with T1=unsigned int, T2=std::allocator<unsigned int>]
Because linkers and other tools don't like names with lots of punctuation, this instantiated name gets mangled to something they can deal with. The rules for name mangling should be part of a C++ ABI. Other aspects include where the implicit this parameter gets passed to a class function, how to manage virtual functions for a class, how to store run-time type information, and how to store information to handle and recover from exceptions.
PGI, like many vendors, licenses the great C++ front end from the Edison Design Group (EDG). When PGI first introduced C++ support with pgCC, we used the mechanisms designed by EDG for C++-specific features. Since that time, C++ has evolved and become more important, and the need for an official ABI became more apparent. About 12 years ago, an informal effort began to define an official ABI for C++, resulting in a C++ ABI document that has been updated many times over the years to support new language features and needs. Many compilers, including the GNU Compiler Collection g++ compiler, implement this newer ABI.
Now, PGI will be implementing this ABI as well. The rest of this article will tell some of the differences, what it will mean for compatibility, and how it will affect you.
Implementing the C++ ABI
The C++ ABI was implemented in three phases. First, we began the transition with the most difficult issue: changing from a setjmp/longjmp implementation of exceptions to the low cost C++ ABI solution. In parallel with this effort, EDG implemented the front end changes required for ABI support and redesigned their internal representation to better represent the C++11 changes to the language. Finally, we made the transition to the new EDG front end, and began the back end work for ABI compiliance.
Some of the ABI features were purely front end issues. These include name mangling, new formats for virtual function tables, and guard initialization. Other features required extensive work by PGI: covariant return functions, this pointer base class adjustments, weak section layouts and of course, low cost exception handling. More work was required to allow the pgCC compiled objects to be link compatibile with gnu objects: native complex support, system include file compatibility, thunk implementation and run time type information changes.
We are currently at EDG release 4.1, and plan to have full C++11 support by mid 2013.
Using the New ABI
Because we don't want to invalidate any existing C++ object files, we can't simply change the ABI implemented by our compilers from one version to the next. Instead, we've added a new command, pgc++, that invokes the PGI C++ compiler and generates code conforming to the new ABI; this is also available by invoking pgcpp --gnu or pgCC --gnu. Users should not mix objects created by pgCC with pgCC --gnu objects.
The new compilers give some important benefits to C++ programmers. First, and most important, is that the new compilers will link with the system C++ libraries, including STL and Boost. This means your STL or Boost-based code will work the same way with the PGI compilers as with other compilers.
There are currently some limitations to our link compatibility with GCC code: Our long double size is not compatible. Users who call functions with long double parameters should compile all of that code with the same compiler. pgc++ supports pthreads except for code compiled -mp (OpenMP). pgc++ calls its own math routines; users should link with pgc++. GNU builtins introduced in 4.4.0 are not yet supported.
pgc++ supports gcc versions 4.1 through 4.5. The compiler installation process determines which g++ version is installed on your machine, and configures your localrc file accordingly. If you upgrade your gcc compiler, you will have to reinstall the PGI compilers.
In this article we present user-visible changes that will be available in the PGI C++ compiler. This is specific to Linux; the new functionality is available by compiling with the pgc++ command, or compiling with pgcpp --gnu. The new compilers use the system C++ libraries, avoiding problems that arise from dealing with another C++ and Standard Template Library.
Of course, the new compilers include all the advanced features that PGI has introduced over the years, such as
- automatic vectorization for the SSE and AVX instructions,
- OpenMP and automatic parallelization for multicore processors,
- PGI Unified Binary to optimize for different target processors in a single executable,
- advanced interprocedural analysis,
- support for remote debugging, and
- CUDA-X86 support.
Support for the standard C++ ABI will let you use the PGI compilers in situations where previously it was simply not feasible, and make it easier to change your build compiler for parts of your application.