On 18 Jun 2004, at 13.23, Richard Henderson wrote:
> On Thu, Jun 17, 2004 at 06:57:40PM -0700, Ziemowit Laski wrote:
>> So, could someone give me some pointers (no pun intended) on how to
>> make the casting of functions into a first-class citizen in the eyes
>> of the back-end?
>
> How about a much much better solution -- not casting at all.
>
> You're wanting to do something special with language implementation
> internals. Seems to me that the best solution is to represent this
> special as well.
>
> We've been talking about various ways to represent method calls in
> C++ and Java such that they can be devirtualized during/after
> optimization. I wonder if a similar approach can be done here?
>
> For instance, if we added a METHOD_CALL_EXPR to GIMPLE, then we
> wouldn't need to expose the objc_msgSend symbol at all at the
> tree level; it wouldn't need to show up until we get to rtl.
Yes, I think that what you suggest could work, albeit at the cost of
having
to add additional machinery to GIMPLE.
How about the following: In my original example,
typedef struct objc_Object * foo_id ;
typedef struct blortstruct *blort ;
extern foo_id objc_msgSend(foo_id, ...);
int main(int argc, char * argv[])
{
blort foo = 0, bar = 0 ;
foo_id obj0;
obj0 = ((foo_id ((*)(foo_id, char *, blort, blort))) &objc_msgSend)
(obj0, "foo message", foo, bar);
return 0;
}
we transform
obj0 = ((foo_id ((*)(foo_id, char *, blort, blort))) &objc_msgSend)
(obj0, "foo message", foo, bar);
into something like:
{
extern foo_id objc_msgSend(foo_id, char *, blort, blort);
obj0 = objc_msgSend (obj0, "foo message", foo, bar);
}
?
Presently, this does not entirely work: :-(
/Volumes/DATA2/Proj/Stuff/msgsendkinky.c: In function `main':
/Volumes/DATA2/Proj/Stuff/msgsendkinky.c:10: error: conflicting types
for `objc_msgSend'
/Volumes/DATA2/Proj/Stuff/msgsendkinky.c:3: error: previous
declaration of `objc_msgSend'
/Volumes/DATA2/Proj/Stuff/msgsendkinky.c:10: warning: extern
declaration of `objc_msgSend' doesn't match global one
But perhaps we could add some __attribute__ (my favorite GCC hammer :-)
) to indicate that we really want a local prototype which shadows a
global one, but only in the scope in which it appears:
{
extern foo_id objc_msgSend(foo_id, char *, blort, blort)
__attribute__((local_prototype));
obj0 = objc_msgSend (obj0, "foo message", foo, bar);
}
?
Actually, wait! How about
{
extern foo_id __objc_msgSend_local_nnnn(foo_id, char *, blort,
blort) asm("objc_msgSend");
obj0 = __objc_msgSend_local_nnnn (obj0, "foo message", foo, bar);
}
instead? What do you think?
--Zem