Overview
I am working on a Clang backend that compiles C++ code with an ABI compatible to GCC 2.95 (referred to as GCC2).
This would be enabled by the -fc++-abi=gcc2 option.
Features
The changes would include:
- Name mangling.
- C++ runtime support function names.
- RTTI.
- Vtable layouts.
- DWARF2 exception handling information.
- Other GCC2-specific ABI quirks.
Scope
Unlike Clang’s MSVC compatibility feature, this effort aims to provide only a reasonable level of binary compatibility only. Source compatibility is not included. This means:
- Changes will strictly be in CodeGen only. No Sema changes will be submitted.
- This means, to achieve the same result, slightly different code may need to be used for modern Clang than GCC2.
- The majority of changes to the shared CodeGen layer will come in the form of ABI/Layout/Vtable hooks and dispatchers/factories that call these hooks.
- Most changes will be done by overriding existing virtual functions. These implementations will be in separate files.
- A limited number of additional hooks will allow the GCC2 backend to provide additional customizations to CodeGen. These hooks will have trivial default implementations that work for both MSVC/Itanium ABIs.
Motivation
GCC2 uses an ABI that is fundamentally incompatible with GCC4+ and Clang, which use the Itanium ABI.
This forces projects relying on ABI-compatibility with GCC2-era binaries, such as the Haiku Operating System, to stick to legacy codebases and legacy C++ versions.
Clang’s modular design, especially after its support for the MSVC ABI, makes it easier to develop a legacy ABI backend while unlocking the latest C++ features provided by the frontend parser.
Impact
Codebase
The implementation should be designed as a Peripheral Tier feature. If not possible, it should aim to follow the tier’s guidelines of sub-community maintenance and minimizing breakages and disturbance as far as practically possible for a tightly integrated project like Clang.
Most of the ABI implementation should be isolated into GCC2-specific files Outside of these files, changes should only be related to command parsing (e.g. supporting -fc++-abi=gcc2) and dispatching to the relevant GCC2 counterparts (as described in the #Scope).
Maintainability Costs
Newer C++ versions may introduce runtime features entirely unknown to GCC2. The most likely affected components is mangling and RTTI, while others like Vtables will more likely incur a one-time cost.
For these features, we will let the compiler fail only when GCC2 is specified, until any interested volunteer handles them. This behavior is already visible in other less-supported targets. For example, with --target=armv7-windows-msvc:
- Until very recently, SEH
__try/__except/__finallywill simply return a compile error. - C++
try/catch, an important language feature, still crashes the compiler.
Since new C++ features are unknown to GCC2 and never used in legacy binaries, there will be room for implementations that are more lax/creative.
Review Costs
We will try to minimize review costs to the LLVM maintainers.
Changes will be small (aiming for < 100 lines of diff for non-GCC2-specific files) with C++98 CodeGen tests acting both as a quick feature demonstration and protection against regression.
While AI tools will be used for exploration, all upstreamed patches will be hand-crafted, following the AI Tool Use Policy.
To prevent wasteful code review for stubs that never get implemented, PRs will only be opened once feasibility has been demonstrated downstream. For this purpose, a software package already supported by the Haiku operating system’s official repository (HaikuPorts) will be chosen and ported to the GCC2 ABI runtime environment. The software must be sufficiently complex (with 10+ C++ source files and a non-trivial build system).
Testing
CodeGen tests will be provided, allowing the project to:
- Safeguard against regressions in new pull requests.
- Provide some form of documentation for the expected behavior in GCC2 binaries, aiding the code review process.
However, these tests may:
- Slow down development speed for newer language features.
- Add overhead to the CI time.
Therefore, the effort aims to provide tests that:
- Are restricted to standard C++98, preventing interference with modern C++ features.
- Are restricted to “non-buggy” behavior reproducible in GCC2. “Non-buggy” should mean cases where GCC2 is already standards-conforming or agrees with modern Clang in how to interpret the relevant source code.
- Are simple (the entire GCC2 CodeGen suite should take <1s total CI time).
This RFC was rejected in this message.