Why does casting a function generate a run-time abort?

Ziemowit Laski zlaski@apple.com
Fri Jun 18 21:13:00 GMT 2004


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



More information about the Gcc mailing list