C/C++ Calling Convention

There has been a number of changes in the past couple of years in the calling conventions of C/C++ code. The processors become a lot more powerful and provide a larger number of available registers, while the traditional calling conventions relying on stack for passing parameters slowly being phased out.

Unfortunately Microsoft and Intel decided to introduce new independent keywords to address performance issues rather than extending existing conventions of __fastcall. Microsoft came up with __vectorcall starting with Visual Studio 2013, while Intel introduced __regcall with Intel C++ 14.0 Update 1, both of which similarly utilize a larger number of registers in function calls.

C/C++ Cross Compiler Compatibility and Calling Conventions

For C and C++ compatibility the only important keyword construct to keep in mind is extern “C” – if you are intending to call C++ functions from C use extern “C” in the function declaration to prevent name mangling. Use the same declaration for C functions for calling them in C++.

Stroustrup C++ FAQ: How do I call a C function from C++?  How do I call a C++ function from C?

Stack Cleanup and Variable Arguments Relationship

Caller stack cleanup generally amounts to a larger generated code base, since for each call there has to be a corresponding stack cleanup in the code that calls the function. Hence calling the same function ten times, you would have ten sections of assembler code which unwinds the stack and arguments.

However, passing variable arguments is only possible with caller stack cleanup. The reason for that is simple – your callee may simply not know how many arguments caller pushed in that stack. Hence, if you are using variable arguments compiler would have to use __cdecl (x86) or __fastcall (x64) convention.

Calling Conventions Keywords

x86 platform: __cdecl, __stdcall, __fastcall, __thiscall, __clrcall, __vectorcall, __regcall, __syscall (obsolete), __pascal (obsolete)

x64 platform: __fastcall, __vectorcall/_regcall

Name Decoration (Mangling):

C++ compilers decorates function names by adding additional information to the function name, i.e. _foo@12 for void foo(int a, int b).

Microsoft has a utility undname.exe which allows you to decode a decorated based on its signature :

Reference: Viewing Decorated Names https://msdn.microsoft.com/en-us/library/5x49w699.aspx

C:> undname.exe ?func1@a@@AAEXH@Z
...
of :- "?func1@a@@AAEXH@Z"
is :- "private: void __thiscall a::func1(int)"

References

Intel: C/C++ Calling Conventions https://software.intel.com/en-us/node/512847
Microsoft: Argument Passing and Naming Conventionshttp://msdn.microsoft.com/en-us/library/984x0h58.aspx
Wikipedia: x86 calling conventions http://en.wikipedia.org/wiki/X86_calling_conventions
Intel: _vectorcall and __regcall Demystified http://software.intel.com/sites/default/files/Vectorcall_regcall_Demystified.pdf
Microsoft: Introducing ‘Vector Calling Convention’ http://blogs.msdn.com/b/vcblog/archive/2013/07/12/introducing-vector-calling-convention.aspx
Calling conventions for different C++ compilers and operating systems http://www.agner.org/optimize/calling_conventions.pdf
Calling Conventions Demystified http://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified
Wikipedia: x86 Disassembly/Calling Conventions http://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions

Leave a Reply

Your email address will not be published. Required fields are marked *