public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* GCC/ObjC enhancements, comments requested
@ 1998-02-07 18:11 Scott Christley
  1998-02-07 22:43 ` Richard Henderson
  1998-02-08 10:27 ` Ovidiu Predescu
  0 siblings, 2 replies; 16+ messages in thread
From: Scott Christley @ 1998-02-07 18:11 UTC (permalink / raw)
  To: egcs

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



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-07 18:11 GCC/ObjC enhancements, comments requested Scott Christley
@ 1998-02-07 22:43 ` Richard Henderson
  1998-02-08 10:21   ` Scott Christley
  1998-02-10 14:45   ` Anthony Green
  1998-02-08 10:27 ` Ovidiu Predescu
  1 sibling, 2 replies; 16+ messages in thread
From: Richard Henderson @ 1998-02-07 22:43 UTC (permalink / raw)
  To: Scott Christley; +Cc: egcs

On Sat, Feb 07, 1998 at 08:17:34PM -0800, Scott Christley wrote:
> * allocation information for loading the stack and register with argument
> and return values.

I guess I don't understand why you don't just pass everything by
reference if you don't know their types.  Seems _much_ cleaner
than trying to get things loaded into random registers.  You at
least know how many arguments you are passing, don't you?  Seems
like that plus references makes the problem non-existant.

> 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.

Won't work.  Its type may change which register it is passed in, 
and furthermore, structure-type arguments may be passed in fragments:
parts in disjoint registers and parts on the stack.

I can't think of any way you could get any coherent description of
where a particular non-scalar object might go.


r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-07 22:43 ` Richard Henderson
@ 1998-02-08 10:21   ` Scott Christley
  1998-02-10  3:34     ` Richard Henderson
  1998-02-10 14:45   ` Anthony Green
  1 sibling, 1 reply; 16+ messages in thread
From: Scott Christley @ 1998-02-08 10:21 UTC (permalink / raw)
  To: Richard Henderson; +Cc: egcs

On Sat, 7 Feb 1998, Richard Henderson wrote:

> On Sat, Feb 07, 1998 at 08:17:34PM -0800, Scott Christley wrote:
> > * allocation information for loading the stack and register with argument
> > and return values.
> 
> I guess I don't understand why you don't just pass everything by
> reference if you don't know their types.  Seems _much_ cleaner
> than trying to get things loaded into random registers.  You at
> least know how many arguments you are passing, don't you?  Seems
> like that plus references makes the problem non-existant.

We do know the types, the issue is that we don't know the types until
runtime, so we must be able to perform the same logic at runtime that GCC
at compile time.

> > 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.
> 
> Won't work.  Its type may change which register it is passed in, 
> and furthermore, structure-type arguments may be passed in fragments:
> parts in disjoint registers and parts on the stack.
> 
> I can't think of any way you could get any coherent description of
> where a particular non-scalar object might go.

How can this be?  GCC somehow must decide how to pass this information; it
is obviously doing it when you compile.  The issue is that we need access
to this logic at runtime.

I'm afraid I haven't explained the task clearly enough.

Scott



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-07 18:11 GCC/ObjC enhancements, comments requested Scott Christley
  1998-02-07 22:43 ` Richard Henderson
@ 1998-02-08 10:27 ` Ovidiu Predescu
  1998-02-08 13:12   ` Marcus G. Daniels
  1 sibling, 1 reply; 16+ messages in thread
From: Ovidiu Predescu @ 1998-02-08 10:27 UTC (permalink / raw)
  To: Scott Christley; +Cc: egcs

On Sat, 7 Feb 1998 20:17:34, Scott Christley wrote:

> 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]);

When you speek about builtin functions you should remember that these  
functions are either generated by the compiler or available in libgcc at  
runtime.

The above three functions cannot be implemented as builtin functions because  
none of the internal structures of GCC are available in the compiled  
programs (there are no tree or rtx objects available in libgcc or libobjc).  
These functions cannot be generated by compiler or included in a runtime  
library without taking a lot of GCC's internal knowledge.

If you thought at these functions as being part of the compiler itself, then  
they don't make sense because the compiler doesn't have to deal with the  
incomplete type specification encoded by Objective-C type strings.

The way I originally saw this runtime construction of a call is to make GCC  
generate this knowledge and implement generic functions in a runtime library  
(libgcc or libobjc) that uses that knowledge to build the call. The public  
API though should be in my opinion written entirely in C, not use any ObjC  
specific classes, so that C programs can use it. In addition the type  
encoding used by this API should not use the plain ObjC type encoding because  
it lacks a lot of type information from the original C type, though it can  
be a good starting point.

--
Ovidiu Predescu <ovidiu@net-community.com> (NeXTMail, MIME)
http://www.net-community.com/Users/~ovidiu

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-08 10:27 ` Ovidiu Predescu
@ 1998-02-08 13:12   ` Marcus G. Daniels
  1998-02-08 22:32     ` Ovidiu Predescu
  1998-02-09 14:46     ` Anthony Green
  0 siblings, 2 replies; 16+ messages in thread
From: Marcus G. Daniels @ 1998-02-08 13:12 UTC (permalink / raw)
  To: Ovidiu Predescu; +Cc: Scott Christley, egcs

>>>>> "OP" == Ovidiu Predescu <ovidiu@aracnet.com> writes:

OP> The way I originally saw this runtime construction of a call is to
OP> make GCC generate this knowledge and implement generic functions
OP> in a runtime library (libgcc or libobjc) that uses that knowledge
OP> to build the call.

Hey, if worse came to worst, "gcc -g" generates this knowledge. 
Looks to me like "objdump --debugging" reports everything that's needed.
Link in GNU BFD and load up them reflection data structures!


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-08 13:12   ` Marcus G. Daniels
@ 1998-02-08 22:32     ` Ovidiu Predescu
  1998-02-09  7:43       ` Bruno Haible
                         ` (2 more replies)
  1998-02-09 14:46     ` Anthony Green
  1 sibling, 3 replies; 16+ messages in thread
From: Ovidiu Predescu @ 1998-02-08 22:32 UTC (permalink / raw)
  To: Marcus G. Daniels; +Cc: Scott Christley, egcs

On 08 Feb 1998 12:59:30, marcusd@cathcart.sysc.pdx.edu (Marcus G. Daniels) wrote:

> >>>>> "OP" == Ovidiu Predescu <ovidiu@aracnet.com> writes:
>
> OP> The way I originally saw this runtime construction of a call is to
> OP> make GCC generate this knowledge and implement generic functions
> OP> in a runtime library (libgcc or libobjc) that uses that knowledge
> OP> to build the call.
>
> Hey, if worse came to worst, "gcc -g" generates this knowledge.
> Looks to me like "objdump --debugging" reports everything that's needed.
> Link in GNU BFD and load up them reflection data structures!

What we're trying to build is a system that allows us to build a function  
call at _runtime_, knowing the address of the function, the argument types  
and the return value. The types would be encoded in a similar way with how  
ObjC currently encodes them, in C strings. GCC currently implements only half  
of this support with the __builtin_apply() and __builtin_return()  
pseudo-functions.

BFD can't help us here because it gives information only on the name of the  
functions contained in an object file, the argument types are lost (at least  
for C and C++ functions, ObjC does encode the argument and return value types  
of each method).

What is needed is a way to access and set the arguments in the frame passed  
to __builtin_apply() and the return value respectively in __builtin_return().  
The knowledge to do this is definitely contained inside GCC, as it is able  
to generate these functions. We need a way to export this knowledge to an  
external library like libgcc.

I think this can be done relatively easy by exporting the tables and the   
register and mode information used by expand_builtin_apply() and  
expand_builtin_return() in expr.c. We can then implement a simple C API that  
works with them to access the __builtin_apply frame; the algorithms  
implemented would duplicate the ones used by the above functions.

--
Ovidiu Predescu <ovidiu@net-community.com> (NeXTMail, MIME)
http://www.net-community.com/Users/~ovidiu

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-08 22:32     ` Ovidiu Predescu
@ 1998-02-09  7:43       ` Bruno Haible
  1998-02-09 15:33         ` Ovidiu Predescu
  1998-02-09 11:31       ` Marcus G. Daniels
  1998-02-10  3:34       ` Richard Henderson
  2 siblings, 1 reply; 16+ messages in thread
From: Bruno Haible @ 1998-02-09  7:43 UTC (permalink / raw)
  To: egcs; +Cc: Ovidiu Predescu

Ovidiu Predescu writes:

> What we're trying to build is a system that allows us to build a function
> call at _runtime_, knowing the address of the function, the argument types
> and the return value. ...
> 
> What is needed is a way to access and set the arguments in the frame passed
> to __builtin_apply() and the return value respectively in __builtin_return().

You can do this with the `avcall' part of the `ffcall' library. Have a look
at

    http://clisp.cons.org/~haible/packages-ffcall.html
    ftp://ma2s2.mathematik.uni-karlsruhe.de/ffcall-1.3.tar.gz

Bruno

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-08 22:32     ` Ovidiu Predescu
  1998-02-09  7:43       ` Bruno Haible
@ 1998-02-09 11:31       ` Marcus G. Daniels
  1998-02-10  3:34       ` Richard Henderson
  2 siblings, 0 replies; 16+ messages in thread
From: Marcus G. Daniels @ 1998-02-09 11:31 UTC (permalink / raw)
  To: Ovidiu Predescu; +Cc: Scott Christley, egcs

>>>>> "OP" == Ovidiu Predescu <ovidiu@aracnet.com> writes:

MD>  Hey, if worse came to worst, "gcc -g" generates this knowledge.
MD> Looks to me like "objdump --debugging" reports everything that's
MD> needed.  Link in GNU BFD and load up them reflection data
MD> structures!

OP> BFD can't help us here because it gives information only on the
OP> name of the functions contained in an object file, the argument
OP> types are lost (at least for C and C++ functions, ObjC does encode
OP> the argument and return value types of each method).

Nuhhhh-uhhhhh!  Lookie:

mgd@wijiji[~] $ cat hello.c
static void
twoargs (int val, const char *msg)
{
  printf ("%d %s\n", val, msg);
}

main ()
{
  twoargs (1, "Hello World");
}

mgd@wijiji[~] $ gcc -g hello.c -o hello
mgd@wijiji[~] $ objdump --debugging hello | less
[....CHOMP....]
static void twoargs (int val /* 0x44 */, char *msg /* 0x48 */)
{ /* 0x108e8 */
  /* file /net/pele/disk12/Users/mgd/hello.c line 3 addr 0x108e8 */
  /* file /net/pele/disk12/Users/mgd/hello.c line 4 addr 0x108f4 */
  /* file /net/pele/disk12/Users/mgd/hello.c line 5 addr 0x1090c */
  /* file /net/pele/disk12/Users/mgd/hello.c line 5 addr 0x1090c */
} /* 0x10914 */
int main ()
{ /* 0x10914 */
  /* file /net/pele/disk12/Users/mgd/hello.c line 8 addr 0x10914 */
  /* file /net/pele/disk12/Users/mgd/hello.c line 9 addr 0x10918 */
  /* file /net/pele/disk12/Users/mgd/hello.c line 10 addr 0x1092c */
} /* 0x10934 */  
[....CHOMP....]


(Now requiring and loading up debugging information is probably much
to expensive a proposition, but clearly the compiler is setup to save
this stuff.)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-08 13:12   ` Marcus G. Daniels
  1998-02-08 22:32     ` Ovidiu Predescu
@ 1998-02-09 14:46     ` Anthony Green
  1 sibling, 0 replies; 16+ messages in thread
From: Anthony Green @ 1998-02-09 14:46 UTC (permalink / raw)
  To: egcs

> What we're trying to build is a system that allows us to build a function  
> call at _runtime_, knowing the address of the function, the argument types  
> and the return value.

I've written a library for doing this exact thing. You can pick it up
at:

	http://www.cygnus.com/~green/libffi.html

AG

-- 
Anthony Green                                               Cygnus Solutions
                                                       Sunnyvale, California

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-09  7:43       ` Bruno Haible
@ 1998-02-09 15:33         ` Ovidiu Predescu
       [not found]           ` <199802092146.WAA04183@halles.ilog.fr>
  0 siblings, 1 reply; 16+ messages in thread
From: Ovidiu Predescu @ 1998-02-09 15:33 UTC (permalink / raw)
  To: Bruno Haible; +Cc: egcs, Ovidiu Predescu

On Mon, 9 Feb 1998 16:41:10, Bruno Haible wrote:

> Ovidiu Predescu writes:
>
> > What we're trying to build is a system that allows us to build a function
> > call at _runtime_, knowing the address of the function, the argument
> > types and the return value. ...
> >
> > What is needed is a way to access and set the arguments in the frame
> > passed to __builtin_apply() and the return value respectively in
> > __builtin_return().
>
> You can do this with the `avcall' part of the `ffcall' library. Have a look
> at
>
> http://clisp.cons.org/~haible/packages-ffcall.html
> ftp://ma2s2.mathematik.uni-karlsruhe.de/ffcall-1.3.tar.gz

Thanks for the pointer Bruno, I've took a look on it several months ago,  
it's really cool! What I would like to see though is a compiler based  
approach as it would be much more easier and straightforward than maintaining  
an additional library.

---
Ovidiu Predescu <ovidiu@net-community.com> (NeXTMail, MIME)
http://www.net-community.com/Users/~ovidiu/ (GNUstep/OPENSTEP free software)

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-08 10:21   ` Scott Christley
@ 1998-02-10  3:34     ` Richard Henderson
  0 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 1998-02-10  3:34 UTC (permalink / raw)
  To: Scott Christley; +Cc: Richard Henderson, egcs

On Sun, Feb 08, 1998 at 12:28:47PM -0800, Scott Christley wrote:
> > I guess I don't understand why you don't just pass everything by
> > reference if you don't know their types.
> 
> We do know the types, the issue is that we don't know the types until
> runtime ...

Which from my point of view counts as not knowing the types.

> ... so we must be able to perform the same logic at runtime that GCC
> at compile time.

Which can be arbitrarily complex for any given target.  Sorry to
rain on your parade, but the calling conventions for Sparc v9 and
MIPS n64, to name two examples, are quite nasty (but efficient)
when it comes to passing structs by value.  

It is sitting in my home directory at the moment, but for a sense
of scope the Sparc v9 function argument and return value macros
are implemented with 12 functions spanning 900 lines -- and I have
yet to add the bits to properly handle C++ nested classes.

> How can this be?  GCC somehow must decide how to pass this information; it
> is obviously doing it when you compile.  The issue is that we need access
> to this logic at runtime.

How?  I can't think of any way at all for you to give direct access
to the backing functions in any coherent fashion.

> I'm afraid I haven't explained the task clearly enough.

The task is clear enough, the reason is not. 

Why is there a requirement that you be able to call arbitrary functions
in the native calling convention?  Why can you not simply pass everything
by reference?  Loading up all pointer registers is a much simpler task.


r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-08 22:32     ` Ovidiu Predescu
  1998-02-09  7:43       ` Bruno Haible
  1998-02-09 11:31       ` Marcus G. Daniels
@ 1998-02-10  3:34       ` Richard Henderson
  1998-02-10 10:58         ` Ovidiu Predescu
  2 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 1998-02-10  3:34 UTC (permalink / raw)
  To: Ovidiu Predescu; +Cc: Marcus G. Daniels, Scott Christley, egcs

On Sun, Feb 08, 1998 at 10:32:37PM -0800, Ovidiu Predescu wrote:
> What we're trying to build is a system that allows us to build a function  
> call at _runtime_, knowing the address of the function, the argument types  
> and the return value.

Why?

> GCC currently implements only half  
> of this support with the __builtin_apply() and __builtin_return()  
> pseudo-functions.

GCC doesn't even pretend to get even these right for targets that 
don't pass all arguments on the stack.  Certainly it doesn't work
on the Alpha, which is one of the simpler examples.


r~

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
       [not found]           ` <199802092146.WAA04183@halles.ilog.fr>
@ 1998-02-10 10:58             ` Ovidiu Predescu
  1998-02-10 14:45               ` Joern Rennecke
  0 siblings, 1 reply; 16+ messages in thread
From: Ovidiu Predescu @ 1998-02-10 10:58 UTC (permalink / raw)
  To: Bruno Haible; +Cc: egcs, Ovidiu Predescu

On Mon, 9 Feb 1998 22:46:28, Bruno Haible wrote:

> > What I would like to see though is a compiler based approach as it
> > would be much more easier and straightforward than maintaining an
> > additional library.
>
> Do you mean the following: Adding enough builtins to gcc so that the
> thing can be performed with a single function largely written in C ?
> (Similar to __throw.)

Not quite builtin functions, in the sense they are expanded by compiler, but  
some functions that are present in libgcc that appear in a header file with  
their needed types so that programs can call them to perform dynamic  
invocations.

> I think it can be done. The only requirement is that gcc emits some
> RTTI-like information for each structure type, containing:
> - the structure size,
> - the structure alignment,
> - a few other bits of information, in order to fix the
> return-in-registers/return-in-memory problem alluded to in the BUGS
> section of the avcall manual page.

I don't like to base the functionality on the information emitted by  
compiler at compile time. The set of functions that can be called is not  
limited to the functions compiled by the compiler; what happens if I write a  
JIT compiler myself and want those functions use the native convention calls?  
I have to do the same thing the compiler does to compile that function.

> I want an API independent of ObjC because the issue arises again for Java.

Me too. I want some things written in plain C, not even C++.

> Before I start putting a lot of thought into it, let's start from the
> beginning.
>
> 1. What do you want to perform? If I understood it well, some ObjC method
> is present at runtime, and is represented by argtype+rettype information,
> plus a code address, plus maybe an object pointer. You want to call
> this method. Where do the arguments for this call come from, originally?

I want to be able to dynamically create invocations of ObjC methods and C  
functions, I explained how this works in another message posted on the group.  
This is definitely possible in ObjC, but only if you have the frame passed  
to __builtin_apply() already constructed; this is possible if you send a  
message to an object that doesn't implement that message. But you don't have  
any standard way to create that frame.

Here is the function that creates the frame when you send a message to an  
object that doesn't implement it:

static id
__objc_word_forward (id rcv, SEL op, ...)
{
  void *args, *res;

  args = __builtin_apply_args ();
  res = __objc_forward (rcv, op, args);
  if (res)
    __builtin_return (res);
  else
    return res;
}

The __objc_word_forward is returned by the runtime system as the method's  
implementation when an object does not implement a method. This function  
calls __objc_forward() that invokes a special method of the object which has  
as arguments the original name of the message and it's arguments in 'args'.  
In that special method one can call objc_msg_sendv() to send the same message  
with the same arguments to another method. Take a look on objc/sendmsg.c to  
see the whole picture.

> 2. How are the types encoded? Elementary types are easy, they are finite
> in number. How about structure types? Are they given as strings (worst)
> or can we pass some RTTI pointer?

Objective-C encodes the types in strings. You can encode both elementary  
types and compound types. For example:

char		c
short		s
int		i
long		l
float		f
double		d

The unsigned versions are with capital letters. Structs are encoded like this:

struct {
  int i;
  char c;
};

is encoded "{ic}". Unions are encoded like "(ic)", arrays between "[" and "]".

A method is encoded like this: first the type of the return value followed  
by the number of bytes occupied by all the arguments on the stack. Then each  
argument is encoded with its type followed by its relative position on the  
__builtin_apply() frame. If the argument is passed on the stack, a '+' sign  
is encoded before the type and the offset is relative to the registers buffer  
in the __builtin_apply() frame. The builtin_apply frame is a structure  
containing two buffers, one for the stack arguments and another one for the  
register arguments. The compiler puts all the arguments in the corresponding  
buffer so the user programs can simply access the arguments without having to  
worry about where the argument might be, if it's partially passed in  
registers and things like this. For

This encoding is quite convinient except for the fact that the compiler  
doesn't encode the size of the registers buffer and doesn't tell you how to  
access the return value in the buffer returned by __builtin_apply. The  
encoding is generated by the compiler when it compiles an ObjC method (see  
objc/objc-act.c/encode_method_prototype()).

What I'd like to have is a new encoding way which says how to access the  
return value, no matter it's passed as reference or by value, and the size of  
the registers buffer. Right now one is able to create a partial frame for  
__builtin_apply containing the stack arguments but he has no way to create  
the registers frame. Also it's though to access the return value.

The second thing would be a runtime function that takes an encoding string  
which has only the method/function types and returns a full encoding that  
gives all the information on how to build/access a __builtin_apply frame.

--
Ovidiu Predescu <ovidiu@net-community.com> (NeXTMail, MIME)
http://www.net-community.com/Users/~ovidiu

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-10  3:34       ` Richard Henderson
@ 1998-02-10 10:58         ` Ovidiu Predescu
  0 siblings, 0 replies; 16+ messages in thread
From: Ovidiu Predescu @ 1998-02-10 10:58 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Ovidiu Predescu, Marcus G. Daniels, Scott Christley, egcs

On Mon, 9 Feb 1998 22:37:17, Richard Henderson wrote:

> On Sun, Feb 08, 1998 at 10:32:37PM -0800, Ovidiu Predescu wrote:
> > What we're trying to build is a system that allows us to build a function
> > call at _runtime_, knowing the address of the function, the argument
> > types and the return value.
> 
> Why?

Objective-C has a special facility called forwarding, which allows you to send a message to an object that does not implement it. A special method is invoked that has as arguments the selector of the original method (a special identifier which represents the message) and the arguments passed to the original message.

This capability is used heavily by Objective-C libraries to implement Distributed Objects, which allow you to have proxies in your application, objects that act for remote objects in another application. Sending a message to a proxy is caught by that special message that sends the selector and the arguments to the remote server application. Note that the server application can run on a different architecture so is essential for the client to identify the arguments and send them one by one to the server. The server creates a frame for __builtin_apply() which contains those arguments, the selector and the object to invoke the message on and eventually invokes the method.
> > GCC currently implements only half  
> > of this support with the __builtin_apply() and __builtin_return()  
> > pseudo-functions.
> 
> GCC doesn't even pretend to get even these right for targets that 
> don't pass all arguments on the stack.  Certainly it doesn't work
> on the Alpha, which is one of the simpler examples.

The above mechanism is hidden inside a class called NSInvocation which is implemented (or at least how I implemented it) by accessing the frame passed to __builtin_apply(). This frame contains information on both stack arguments and register arguments. It is supposed to hide the details of where the compiler puts a specific argument and it should work on all the systems. I'm surprised if this is broken under Alpha since Objective-C relies heavily on these two pseudo-functions.

Ovidiu

--
Ovidiu Predescu <ovidiu@net-community.com> (NeXTMail, MIME)
http://www.net-community.com/Users/~ovidiu


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-07 22:43 ` Richard Henderson
  1998-02-08 10:21   ` Scott Christley
@ 1998-02-10 14:45   ` Anthony Green
  1 sibling, 0 replies; 16+ messages in thread
From: Anthony Green @ 1998-02-10 14:45 UTC (permalink / raw)
  To: egcs

rth@cygnus.com (Richard Henderson) writes:

> Which can be arbitrarily complex for any given target.  Sorry to
> rain on your parade, but the calling conventions for Sparc v9 and
> MIPS n64, to name two examples, are quite nasty (but efficient)
> when it comes to passing structs by value.  

Yes they are nasty, but manageable.  I don't believe n64 is really
that much more complex than n32, which I have working in libffi
(although GCC doesn't get it right).  Perhaps these ABIs seem nastier
than they really are when you are constrained by the framework GCC
provides for describing them.

I just read Scott's proposal.  It seems to me that adding this
facility to GCC is a mistake, and that it more properly belongs as a
seperate library.  Yes, GCC knows about the various calling
conventions, but it really doesn't provide anything you can take
advantage of to make the task of dynamic function call invocations any
simpler.

Try either libffi or Bruno Haible's library.

AG

-- 
Anthony Green                                               Cygnus Solutions
                                                       Sunnyvale, California

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: GCC/ObjC enhancements, comments requested
  1998-02-10 10:58             ` Ovidiu Predescu
@ 1998-02-10 14:45               ` Joern Rennecke
  0 siblings, 0 replies; 16+ messages in thread
From: Joern Rennecke @ 1998-02-10 14:45 UTC (permalink / raw)
  To: ovidiu; +Cc: haible, egcs, ovidiu

> I don't like to base the functionality on the information emitted by  
> compiler at compile time. The set of functions that can be called is not  
> limited to the functions compiled by the compiler; what happens if I write a  
> JIT compiler myself and want those functions use the native convention calls?  
I think then the JIT compiler would have to provide this information.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~1998-02-10 14:45 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-02-07 18:11 GCC/ObjC enhancements, comments requested Scott Christley
1998-02-07 22:43 ` Richard Henderson
1998-02-08 10:21   ` Scott Christley
1998-02-10  3:34     ` Richard Henderson
1998-02-10 14:45   ` Anthony Green
1998-02-08 10:27 ` Ovidiu Predescu
1998-02-08 13:12   ` Marcus G. Daniels
1998-02-08 22:32     ` Ovidiu Predescu
1998-02-09  7:43       ` Bruno Haible
1998-02-09 15:33         ` Ovidiu Predescu
     [not found]           ` <199802092146.WAA04183@halles.ilog.fr>
1998-02-10 10:58             ` Ovidiu Predescu
1998-02-10 14:45               ` Joern Rennecke
1998-02-09 11:31       ` Marcus G. Daniels
1998-02-10  3:34       ` Richard Henderson
1998-02-10 10:58         ` Ovidiu Predescu
1998-02-09 14:46     ` Anthony Green

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).