This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

GCC/ObjC enhancements, comments requested




PORTABLE DYNAMIC INVOCATION

Enhance GCC so that it can correctly perform dynamic invocation of C
functions, more properly the call instruction for the processor, on any
GCC supported platform.  Currently GCC attempts to provide this capability
through the builtin_apply family of functions.  However, the current
implementation is insufficient because it does not take the
return/argument types and the architecture specific stack/register loading
into account.  This capability is essential to the portability and
feasibility of ObjC for any GCC supported platform.

This document details enhancements to be made to the GCC compiler and the
ObjC runtime library.  Implementation details are provided if possible
otherwise the interface for the functionality is provided.  There are two
parts; the first part consists of modifications to the GCC backend to
correct the deficiencies of the current implementation, and the second
part consists of additional ObjC classes added to the ObjC runtime library
which provide an object-oriented interface to the GCC compiler backend
implementation.


GCC backend support

As stated before, the current implementation in the GCC backend is
deficient.  What needs to be determined is exactly how much functionality
is to be provided versus functionality that can be delegated to front-end
languages or users.

In order to properly perform a dynamic call instruction this information
must be known:

* type information for the arguments and return value.
* allocation information for loading the stack and register with argument
and return values.
* A memory address where the call instruction is to transfer execution.

The type information cannot be known by the GCC backend a-priori, so the
user is required to supply this information; likewise, the memory address
must also be supplied by the user.  The allocation information can be
constructed based upon the type information for the arguments and return
value, but calls which have the identical type information will also have
the same allocation information, so its possible to calculate this
information once and cache it so that subsequent calls just retrieve the
information from the cache.  At this point in time, the GCC backend will
not provide caching capability; instead, user (front-end languages) must
provide this if so desired.

So the proposal is to add three builtin functions.

This function is given a type string and pointers to two buffers where it
will store its output.  The function will traverse through the type string
and for each argument store a 0 (zero), if the argument is passed in a
register, or a 1 (one), if the argument is passed on the stack, into
buffer; if the argument is passed on the stack then the stack size will be
stored into sizes.  The type string uses the encoding characters as
defined by the ObjC runtime library; the first character representing the
return value with the additional characters representing the arguments.

void
builtin_allocation(char *types, int *buffer, int *sizes);

This function is given a type string and returns the type information in
internal GCC format.

tree
builtin_convert_type(char *types);

This function is similar to the existing builtin_apply function except
that it has two additional argument; one which contains type information,
in internal GCC format, for the arguments and return value, and the other
which is a two element array that points to register/stack allocation
information.

static rtx
builtin_perform (rtx function, rtx arguments, rtx argsize, tree types, int
*allocation[2]);


ObjC Runtime Library Support

The ObjC runtime library will provide an interface to the GCC backend
implementation through a set of ObjC classes.  The initial design of these
classes was taken from the OpenStep specification, but they have been
significantly modified to provide invocation of normal C functions as well
as ObjC methods.

Class Hierarchy
	Object
		Invocation
			MethodInvocation
		InvocationSignature
			MethodSignature



An Invocation is a call instruction, like a C function, rendered static.
An Invocation contains all the elements of a call instruction: a call
pointer, arguments, and the return value. Each of these elements can be
set directly, and the return value is set automatically when the
Invocation is dispatched.

An Invocation can be repeatedly dispatched; its arguments can be modified
between dispatch for varying results; even its call pointer can be changed
to another with the same invocation signature (argument and return types).
This makes it useful for repeating messages with many arguments and
variations; rather than retyping a slightly different expression for each
message, you modify the Invocation as needed each time before dispatching
it to a new target.

@interface Invocation

+ (Invocation *)invocationWithSignature:(InvocationSignature *)signature;

- (void *)callPointer;
- (void)getArgument:(void *)buffer atIndex:(int)index;
- (void)getReturnValue:(void *)buffer;
- (void)invoke;
- (InvocationSignature *)signature;
- (void)setArgument:(void *)buffer atIndex:(int)index;
- (void)setCallPointer:(void *)pointer;
- (void)setReturnValue:(void *)buffer;

@end


A MethodInvocation is a subclass of Invocation which is specifically for
ObjC methods.  A MethodInvocation requires a selector to be specified
versus a call pointer, and a target object which will receive the ObjC
method invocation.  Like Invocation, a MethodInvocation can be repeatedly
dispatched; allowing its arguments, target object, and selector to
changed; the selector can only be changed to one with the same
MethodSignature.

@interface MethodInvocation

+ (MethodInvocation *)methodInvocationWithSignature:(MethodSignature
*)signature;

- (void)getArgument:(void *)buffer atIndex:(int)index;
- (void)getReturnValue:(void *)buffer;
- (void)invoke;
- (void)invokeWithTarget:(id)anObject;
- (MethodSignature *)signature;
- (SEL)selector;
- (void)setArgument:(void *)buffer atIndex:(int)index;
- (void)setReturnValue:(void *)buffer;
- (void)setSelector:(SEL)selector;
- (void)setTarget:(id)anObject;
- (id)target;

@end


An InvocationSignature records type information for the arguments and
return value of an invocation.  It is then used to create an Invocation,
which can be assigned values for the call pointer and the arguments,

An InvocationSignature presents its argument types by index with the
getArgumentTypeAtIndex: method.  In addition to the argument types, an
invocationSignature offers the total number of arguments with
numberOfArguments, the total stack frame length occupied by all arguments
with frameLength (this varies with hardware architecture), and the length
and type of the return value with methodReturnLength and methodReturnType.

@interface InvocationSignature

-(const char *)getArgumentTypeAtIndex:(unsignedint)index;
- (unsigned int)frameLength;
- (unsigned int)returnLength;
- (char *)returnType;
- (unsigned int)numberOfArguments

@end



A MethodSignature records type information for the arguments and return
value of an ObjC method. It's used to forward messages that the receiving
object doesn't respond tomost notably in the case of distributed objects.
A MethodSignature is typically created using Object's
methodSignatureForSelector: instance method. It's then used to create an
Invocation, which is passed as the argument to a forwardInvocation:
message to send the invocation on to whatever other object can handle the
message. In the default case, Object invokes doesNotRecognizeSelector:,
which generates an error. For distributed objects, the Invocation is
encoded using the information in the MethodSignature and sent to the real
object represented by the receiver of the message.

A MethodSignature presents two additional hidden arguments for every ObjC
method, self and _cmd, which are at indices 0 and 1 respectively. The
arguments normally specified in a invocation follow these.  Applications
using distributed objects can determine if the method is asynchronous with
the isOneway method.

@interface MethodSignature

-(const char *)getArgumentTypeAtIndex:(unsignedint)index;
- (unsigned int)frameLength;
- (BOOL)isOneway
- (unsigned int)returnLength;
- (char *)returnType;
- (unsigned int)numberOfArguments

@end

To support the signature/invocation classes within the ObjC runtime
library, a number of methods are added to the root class, Object.

@interface Object

- (MethodSignature *)methodSignatureForSelector:(SEL)selector;
- (void)forwardInvocation:(MethodInvocation *)invocation;

@end




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]