Georg-Johann Lay <avr@gjlay.de> writes:
Hi, proplems arise here:
struct S
{
void (*foo)(void);
void (*cb)(void) __attribute__((callback));
};
void caller (struct S s, struct S *ps)
{
s.cb(); // #1
ps->cb(); // #2
}
Call #2 seems to work, REG_EXPR yiels a COMPONENT_REF.
But for call #1 REG_EXP is NULL_TREE in final, and so is the
corresponding MEM_EXPR of the enclosing MEM.
So the middle-end nullifies all informations about the callee or never
makes an effort to get it.
The middleend is an ocean of information, but hardly a drop of water
reaches the desert of the backend... :-(
In some cases, call #1 gives a non-NULL_TREE REG_EXPR, but it then is
a PARM_DECL and you do knot know which component is the one that is
being called.
You're right, I wouldn't expect a case like this to work, as there is no
convenient tree for the RTL to refer to. If you need it to work, then I
think you will need to somehow annotate the call rtx itself. There is
no existing mechanism for carrying general function call attributes
through to RTL.
I'm not 100% sure that for this kind of case that attribute will always
survive in GIMPLE, either. I could easily imagine code like this:
s.cb();
s.cb();
being turned into
temp = s.b;
(*temp)();
(*temp)();
and in that case the attribute might be lost.
I'm not certain that you can do this completely reliably without
frontend changes.