1 /* -*- mode: hugs-c; -*- */
2 /* -----------------------------------------------------------------------------
3 * Foreign Function calls
5 * Copyright (c) 1994-1998.
7 * $RCSfile: ForeignCall.c,v $
9 * $Date: 1998/12/02 13:28:21 $
10 * ---------------------------------------------------------------------------*/
16 #include "Assembler.h" /* for CFun stuff */
17 #include "Evaluator.h"
18 #include "ForeignCall.h"
20 /* the assymetry here seem to come from the caller-allocates
21 * calling convention. But does the caller really allocate
25 void hcall( HFunDescriptor* d, StablePtr fun, void* as, void* rs)
28 /* out of date - ADR */
29 marshall(d->arg_tys,as);
31 unmarshall(d->result_tys,rs);
37 /* By experiment on an x86 box, we found that gcc's
38 * __builtin_apply(fun,as,size) expects *as to look like this:
39 * as[0] = &first arg = &as[1]
44 * on an x86, it returns a pointer to a struct containing an
45 * int/int64/ptr in its first 4-8 bytes and a float/double in the next
49 * as[0] = &first arg = &as[2]
50 * as[1] = where structures should be returned
55 * This is something of a hack - but seems to be more portable than
56 * hacking it up in assembly language which is how I did it before - ADR
58 void ccall( CFunDescriptor* d, void (*fun)(void) )
61 char* tys = d->arg_tys;
62 /* ToDo: the use of ARG_SIZE is based on the assumption that Hugs
63 * obeys the same alignment restrictions as C.
64 * But this is almost certainly wrong!
65 * We could use gcc's __va_rounded_size macro (see varargs.h) to do a
69 void *as=alloca(4 + d->arg_size);
70 StgWord* args = (StgWord*) as;
71 *(void**)(args++) = 4 + (char*)as; /* incoming args ptr */
73 args += unmarshall(*tys,args);
75 rs = __builtin_apply(fun,as,(char*)args-(char*)as-4);
76 #elif sparc_TARGET_ARCH
77 void *as=alloca(8 + d->arg_size);
78 StgWord* args = (StgWord*) as;
80 *(void**)(args++) = (char*)as; /* incoming args ptr */
81 *(void**)(args++) = 0; /* structure value address - I think this is the address of a block of memory where structures are returned - in which case we should initialise with rs or something like that*/
83 args += unmarshall(*tys,args);
85 argcount = ((void*)args - as);
86 ASSERT(8 + d->arg_size == argcount);
92 rs = __builtin_apply(fun,as,argcount);
94 #error Cant do ccall for this architecture
97 /* ToDo: can't handle multiple return values at the moment
98 * - it's hard enough to get single return values working
100 if (*(d->result_tys)) {
101 char ty = *(d->result_tys);
102 ASSERT(d->result_tys[1] == '\0');
106 /* ToDo: is this right? */
107 marshall(ty,(char*)rs+8);
116 CFunDescriptor* mkDescriptor( char* as, char* rs )
118 /* ToDo: don't use malloc */
119 CFunDescriptor *d = malloc(sizeof(CFunDescriptor));
122 d->arg_size = argSize(as);
124 d->result_size = argSize(rs);
128 #endif /* INTERPRETER */