[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [f-cpu] New suggestion about call convention

On Sat, Nov 09, 2002 at 11:51:52AM +0000, cedric wrote:
> > No problem, there is a solution for that. If A, B and C form a loop,
> > you can put a `save-all' wrapper around one of them, and the loop will
> > be broken.
> > The only thing that matters is the register set of the callee; if
> > that set is empty, you can delete the (caller; callee) edge from the
> > graph, the loop vanishes, and you can handle the rest like any other
> > non-recursive function. Inserting a `save-all' wrapper by definition
> > empties the register set, so...
> Well it's not so easy. What append if :
> A call B
> B call C
> C call an external function
> This external function call A.

This is easy, again. All external functions are required to have an empty
`used register' set - that is, they will save registers on their own.

This applies in the following cases:

	- the function resides in a(nother) shared library, or is called
	  from there (inter-module call)

	- another function takes its address and passes it around. In
	  this case, the address must point to a `save-all' wrapper,
	  but the program is still allowed to use the `quick' entry
	  point for direct calls.

> You don't have any information about the external function, so you must save 
> all register before calling it (I really mean all, not only the one that used 
> by C, but the one that are used by B too, because B will certainly crash 
> them).

You must save at only one place: At the `public' entry point of A that
is used by the external function (because A is external from the external
functions point of view).

> So we must detect call back function, but that not so easy. Of course you have 
> pointer to function, it's easy to say that their are callback, but sometime 
> you give fixed name to callback, and in that case you can't detect them (With 
> some graphical toolkit, I remember that I used a "callback" to initialise the 
> interface before the interface call it. So it's not because a function is 
> call in your source code, that it isn't a callback).
> This is a very big problem of your algorithm. The only solution is to use a 
> call-graph to know who call each function and to link it with every 
> library...

That won't help at all. Remember that a shared library may be replaced by
a new version which may behave differently (*after* the program has been
linked). Due to that, we will never be able to optimize register usage
across the `border' of a shared library. Therefore, shared libraries
have to be `isolated', and have to save registers.

> In fact the problem is that you can take a decision only if you totally know 
> the world around your program ! That's a big problem.

Therefore, the interface to `the world around' is clearly specified.
And it looks exactly like what you would expect without any link time
optimizations - that is, it will be compatible even with `dumb' linkers.

In fact, link time register relocation (I guess I'll call it LTRR from now
on) is an optional step. Legacy compilers will generate code that always
saves registers, and will not provide optimization hints. LTRR-aware
compilers provide hints and a corresponding `quick' entry point for
each function. Dumb linkers will always use the `register-saved' entry
point of a function - because that's all they can `see'. That way,
full compatibility is maintained.

 Michael "Tired" Riepe <Michael.Riepe@stud.uni-hannover.de>
 "All I wanna do is have a little fun before I die"
To unsubscribe, send an e-mail to majordomo@seul.org with
unsubscribe f-cpu       in the body. http://f-cpu.seul.org/