Better support for Objective-C

Adam Fedor fedor@doc.com
Tue Feb 29 15:49:00 GMT 2000


Hello, I hope in this long email to get more support/help/discussion
regarding Objective-C, GCC's long-lost little cousin to C and C++.

The biggest problem we are having now is with two key parts of
Objective-C - message forwarding and invocations. Both are related in
the sense that they involve constructing an argument frame for a
function, calling the function with the aguments in the argument
frame, and returning the result.  Note that in Objective-C, all the
knowledge about the number, types, and values of the arguments in a
function call must be accessable at runtime. The runtime has no
control over whether the arguments are passed by value or reference,
that is up to the Objective-C user/developer.

Currently this is accomplished in gcc using __builtin_apply and
related functions in gcc, which is broken on several
architectures. I've read all the gcc mailing-list emails about the
evils of __builtin_apply, so I'm fairly sure that there's nothing I
can do to get this fixed, so my current thoughts are to use a library
like libffi (or something similar). The problem with libffi currently
is it does not do frame decomposition (getting argument values from an
already constructed argument frame).

I've talked extensively with Ovidiu Predescu, GCC's Objective-C
maintainer about this. His proposal was to have the compiler construct
some sort of table that would give the relative offsets of the
arguments in a frame given the type of argument and previous
argument. Combined with a function like __builtin_save_regs(), this
would allow us to determine the arguments which we could pass to the
libffi functions.  I've attached some other thoughts from Ovidiu at
the end of this post.

My question is, do you have any thoughts on the best way to accomplish
this?  I, and most people I know have very little knowledge of
compilers, so we realy need help from some knowledgable poeple on how
to solve this problem.

====================================================================

If you still don't understand why we need this, see the following
example:

This is a simple psuedo-code example of how an object can delegate
tasks to another object, but the code for doing 'distributed objects'
(remote method invocation) would use almost identical logic. I've
written this to look something like C++ to make it more familiar, but
the code is really Objective-C -- for instance every function call
implicitly passes the called object as the first argument and the
function 'selector' (a unique reference to the function name) as the
second argument.

class DelegateObject : public Object {
  char delegateFunction(double number, some_struct_t structure, int
*ptr);
}

class DelegatingObject : public Object {
  DelegateObject delegate;
}

retval_t DelegatingObject::forward(SEL selector, arglist_t argFrame)
{
  return objc_msg_send(delegate, selector, argFrame);
}

...And in some user code:

void someFunction()
{
  char result;
  double a;
  some_struct_t b;
  int c;
  DelegatingObject *object;

  [... some code ...]
  result = object->delegateFunction(a, b, &c);
}

Note: There is no need to declare a function in a class - here
someFunction sends the message delegateFunction to DelegatingObject
even though the DelegatingObject doesn't declare or implement this
function -- the Objective-C runtime determines that DelegatingObject
does not implement this function and thus calls DelegatingObject's
'forward' function with the argument information, DelegatingObject
then just _forwards_ this information to it's delegate.  This is done
by using the Objective-C runtime function objc_msg_send, which looks
up the function pointer for the function named in 'selector' for the
object 'delegate', and calls this function using the arguments in the
argFrame, and then returns the result.

------------------------------------------------------------------------

Ovidiu Predescu wrote:

I still believe we can come up with such an algorithm and have the
compiler
generate the necessary data for the algorithm to work on a given
machine.

There are several issues that need to be solved however. One issue is
saving
the state of the registers and the relevant info on the stack in a given
memory
location that's used by the invocation library. This may involve some
assembly
language written for each target, although we may also be able to take
advantage of the __builtin_save_regs().

Another issue is that we need to solve is a way to describe what is the
location of compound data in memory and/or registers and correspondingly
in the
saved memory location I described above. This however should be a detail
that
is hidden from the programmer of the API anyway.

And finally, the last thing is invoking the method and restoring the
registers
to the appropriate values.

The whole thing might end up being a library similar with libffi so we
should
probably look at how we can leverage the code that's already being
written by
other people. I'm not sure however how can we do this.


-- 
Adam Fedor, Digital Optics          | Fudd's law of opposition: Push
fedor@doc.com                       | something hard enough, and it will
fedor@gnu.org (GNUstep!)            | fall over.


More information about the Gcc mailing list