How are registers and other information preserved during function calls in C?

2.3k Views Asked by At

Let us say I have three functions, f1(), f2(), and f3(). When f1 is called, it stores information in CPU registers (and I imagine there is other important information as well). Now, depending on a condition that is unknown at compile-time, f1 will call either f2 or f3. f2 and f3 use very different registers, some of which may overlap with those used by f1. Is the following reasoning correct?

The compiler knows which registers a particular function needs during its execution. Therefore, when f1 calls either f2 or f3, the function call code preserves those registers that f2 or f3 use on the stack, regardless of whether or not they are being used by f1.

Or is there some other mechanism by which the compiler preserves registers so that the function that is being returned to doesn't lose its data?

3

There are 3 best solutions below

0
cdcdcd On BEST ANSWER

I think as others have stated the arguments for a function are typically sent down via a number of registers (thereafter on the stack). Which registers are used depends on the compiler – for gcc see GNU C/assembler: http://cs.lmu.edu/~ray/notes/gasexamples/

A number of principles worth noting:

  1. stack frame

  2. caller (the function calling f1) and callee functions (your f1, f2... functions)

  3. volatile and non-volatile registers. For your question you only don't need to worry about non-volatile registers.

Each function has a stack frame, this is an expandable block of the stack that temporarily stores data that needs to be loaded in and out of registers.

Before each function call (to the callee from the caller) the values you wish to pass down, i.e. your arguments, will be placed in a number of preordained registers (typically 4-6 depending on a the compiler – see link); if there are more arguments than the number of preordained registers then these additional values are stored on the stack (typically the callers stack frame).

If these preordained registers are being used by the caller, then the compiler will push these values onto the caller's stack frame before assigning the arguments to the registers before making the call to the callee (e.g. your f1 function). Once the called function (callee) returns, these values are restored to their respective registers from the stack.

It doesn't matter how or what order a series of functions are called the same system is followed when the compiler converts your C code to assembly/opcode.

0
Paul Ogilvie On

"The compiler knows which registers a particular function needs during its execution."

No, it will generally not know this.

For one reason, a function can be from a (third party) library about which the compiler knows nothing. For another reason, what if that function calls another function, and another etetera?

The compiler will just push all "suspect" registers onto the stack and pops them before returning.

0
Basile Starynkevitch On

Recall that a programming language is a specification in a document. For C11, read n1570.

Registers do not exist in C (in other words, the nearly obsolete register keyword is no more related to processor registers). They only matter in machine code (often generated by a C compiler).

However, the code generated by a given compiler (for a given instruction set and target system) obey to some conventions, notably the calling conventions and the ABI (read the system V x86-64 ABI governing Linux for an example). Thes conventions define how registers should be used, and which registers are callee-saved or caller-saved. Register allocation is a difficult part of an optimizing compiler's job.

Often the compiler would emit code to spill some of the registers content into the call stack. And a given register can be used for several things (e.g. it could keep two different variables, if they occur in different places in the same function).

In general the calling convention does not depend upon the called function (recall that you can make indirect calls thru function pointers), but mostly of its signature.