You can only have real confidence in a compiler if you know it’s been rigorously tested. While testing a compiler against the relevant language specification is relatively straightforward, ensuring that it correctly exercises complex features of the target architecture is a lot more difficult. One area that often causes problems is function calling, because from the perspective of the language standard it is not clear how incredibly complex function calling can be. Since complexity invites errors, function call testing warrants extra attention.
We all know the importance of functions. They are the fundamental building blocks that make applications modular and maintainable. One function can call another, pass data to it and get data back from it. Where and how this data is stored is target architecture dependent and defined by a calling convention. The calling convention is an important part of the ABI, the Architecture Binary Interface, which also defines the representation of primitive and structured data types. Because function calls typically occur very frequently, calling conventions are optimized for speed and are highly integrated with the compiler’s register allocator, which is often complex in itself. Yet in the face of this complexity, the calling conventions must provide a dependable interface. Pre-compiled library functions, and functions compiled with different compiler options, must work well together when linked into a single application.
Testing within and between compilers
Testing function calls requires a minimum of two functions, a caller and a callee. If these two functions can be compiled independently, one way of testing the calling convention is to use different compiler options for each function and then check the consistency of parameter passing between the two functions. If application code is linked to a library that is compiled with an older version of the currently used compiler, the stability of the calling convention can be tested by compiling the two test functions with the two versions of the same compiler. For mainstream target architectures, where it’s highly likely that pre-compiled library functions will have been compiled by a different compiler, it is extremely important to check that these functions obey the same calling conventions so that they remain interoperable.
SuperTest Vermeer Release Update #1
SuperTest already had a generator for creating function pairs as described above, but its configuration and use was not so easy. With the new update to SuperTest – the first update to the SuperTest Vermeer Release – this has changed dramatically. The calling convention tester is now so easy to use that there is no excuse for not using it during any compiler validation. It generates a comprehensive set of function pairs with a configurable range of argument values and return types to test calling conventions to their limits.
Although calling conventions, and the other parts of the ABI, are not explicitly described in the C and C++ language standards, the function call is one of the most important programming constructs. We believe that the verification of function calls, in all their diversity, is an essential element in building confidence in any compiler.
If you would like to know more about function call testing, or you have any other questions about compiler testing or Update #1 to the SuperTest Vermeer Release, please contact us. We would also be happy to meet you at our booth #4A-325 at Embedded World on February 25-27 in Nuremberg, Germany.