CBFalconer wrote:
What you are looking for is not a language dependency, but a run-time system dependency. This sort of interaction cannot be understood in general, so you would be better off understanding the basic mechanisms used in various systems. Move to a different machine or even compiler and the rules may be entirely different.
Most popular systems are built around the concept of a stack today, and usually (but not always) use this to pass parameters.
Indeed modern architectures use (also) registers to pass parameters. However, the passing conventions are the same between GPC and GCC (by the shared backend) and also between GCC and most other C compilers (by platform ABIs). So this should not actually be an issue.
Parameters can be passed in two basic forms, by value, or by reference. In C there is no reference, instead a pointer to the "referenced" parameter is passed by value. In Pascal, a parameter passed by reference is characterised by the VAR attribute, i.e. its value can be varied by the called function/procedure, and the default parameter passing mechanism is by value.
Correct.
The next fundamental thing to know about a parameter passing mechanism is the order. Some systems pass them in the order mentioned in the function header, and some in the reverse direction. Pascal *tends* to use the order mentioned, and C *tends* to use the reverse order, so that the first C parameter will normally be at the top of the stack when the call is made.
However, GPC by default (i.e., unless overriden by attributes) uses the "C convention" (right to left). So also no problem WRT C vs. GPC here.
Another fundamental variation is "who is responsible for removing parameters from the stack". In Pascal a function is always called with a fixed list of parameters, so the code to remove it need be only in one place, and this is most efficiently done in the called function.
Also here, GPC's default is the C convention. BTW, it's not necessarily worse: The caller can choose to do several calls in sequence and remove all parameters at the end (provided there are no control flow breaks, and parameters are not too large), which the GCC backend actually does. So the number of such pop statements in the binary might be the same or higher, and but number of pops done at runtime can actually be smaller.
A further kettle of worms is 'what is the mechanism for returning function values'. In C the caller can simply ignore the returned value, thus discarding it. In Pascal such failure is an error. Thus C tends to return values in registers, where they can be simply overwritten at any time, and Pascal oftern returns them on the stack, where they must be specifically removed to avoid fouling the stack.
I'm not sure if that's really so common. I've seen other Pascal compilers (even one of the less optimizing ones out there ...) return values in registers. Again, GPC defaults to the C convention.
AFAIK the only language to specify general means of calling routines written in other languages is Ada. C++ has provisions for calling C routines. However these abilities only apply to the use of specified compilers and libraries.
Yes, there's no compiler-independent way. But talking compiler specific, calling between GPC and GNU C (and also GNU C++ when using the C compatibility features on both sides) is quite reliable -- and then it's system-portable. (We use this mechanism in the RTS and some of the included units, so if it failed on some platform, we'd know quickly.)
A hardware platform may also specify specific calling protocols and mechanisms, which can ease creation of compilers etc. that provide interoperability. The IBM 360 and successors, and the HP3000, had such specifications.
I think almost any platform has such an ABI -- whether it was written by the processor, OS or (first) compiler makers, I don't know in general. GCC generally follows the system ABI where one exists, and provides its own one where it's the default compiler (GNU Hurd, Linux).
Frank