8
avcall - build a C argument list incrementally and call a
12
##iinncclluuddee <<aavvccaallll..hh>>
14
aavv__aalliisstt _a_l_i_s_t;;
16
aavv__ssttaarrtt___t_y_p_e((_a_l_i_s_t,, _&_f_u_n_c [[,, _r_e_t_u_r_n___t_y_p_e],, _&_r_e_t_u_r_n___v_a_l_u_e
19
aavv___t_y_p_e((_a_l_i_s_t,, [_a_r_g___t_y_p_e,,] _v_a_l_u_e));;
21
aavv__ccaallll((_a_l_i_s_t));;
23
DDEESSCCRRIIPPTTIIOONN
24
This set of macros builds an argument list for a C func-
25
tion and calls the function on it. It significantly
26
reduces the amount of `glue' code required for parsers,
27
debuggers, imbedded interpreters, C extensions to applica-
28
tion programs and other situations where collections of
29
functions need to be called on lists of externally-sup-
32
Function calling conventions differ considerably on dif-
33
ferent machines and _a_v_c_a_l_l attempts to provide some degree
34
of isolation from such architecture dependencies.
36
The interface is like ssttddaarrgg(3) in reverse. All of the
37
macros return 0 for success, < 0 for failure (e.g., argu-
38
ment list overflow or type-not-supported).
40
(1) ##iinncclluuddee <<aavvccaallll..hh>>
41
and declare the argument list structure
42
aavv__aalliisstt _a_l_i_s_t;;
44
(2) Set any special flags. This is architecture and
45
compiler dependent. Compiler options that affect
46
passing conventions may need to be flagged by
47
##ddeeffiinnees before the ##iinncclluuddee <<aavvccaallll..hh>> statement.
48
However, the _c_o_n_f_i_g_u_r_e script should have deter-
49
mined which ##ddeeffiinnees are needed and put them at the
50
top of aavvccaallll..hh.
52
(3) Initialize the alist with the function address and
53
return value pointer (if any). There is a separate
54
macro for each simple return type ([u]char,
55
[u]short, [u]int, [u]long, [u]longlong, float, dou-
56
ble, where `u' indicates `unsigned'). The macros
57
for functions returning structures or pointers
58
require an explicit type argument.
73
aavv__ssttaarrtt__iinntt ((_a_l_i_s_t,, _&_f_u_n_c,, _&_i_n_t___r_e_t_u_r_n));;
75
aavv__ssttaarrtt__ddoouubbllee ((_a_l_i_s_t,, _&_f_u_n_c,, _&_d_o_u_b_l_e___r_e_t_u_r_n));;
77
aavv__ssttaarrtt__vvooiidd ((_a_l_i_s_t,, _&_f_u_n_c));;
79
aavv__ssttaarrtt__ssttrruucctt ((_a_l_i_s_t,, _&_f_u_n_c,, _s_t_r_u_c_t___t_y_p_e,, _s_p_l_i_t_t_a_b_l_e,,
80
_&_s_t_r_u_c_t___r_e_t_u_r_n));;
82
aavv__ssttaarrtt__ppttrr ((_a_l_i_s_t,, _&_f_u_n_c,, _p_o_i_n_t_e_r___t_y_p_e,,
83
_&_p_o_i_n_t_e_r___r_e_t_u_r_n));;
85
The _s_p_l_i_t_t_a_b_l_e flag specifies whether the _s_t_r_u_c_t___t_y_p_e can
86
be returned in registers such that every struct field fits
87
entirely in a single register. This needs to be specified
88
for structs of size 2*sizeof(long). For structs of size <=
89
sizeof(long), _s_p_l_i_t_t_a_b_l_e is ignored and assumed to be 1.
90
For structs of size > 2*sizeof(long), _s_p_l_i_t_t_a_b_l_e is
91
ignored and assumed to be 0. There are some handy macros
93
aavv__wwoorrdd__sspplliittttaabbllee__11 ((_t_y_p_e_1))
94
aavv__wwoorrdd__sspplliittttaabbllee__22 ((_t_y_p_e_1,, _t_y_p_e_2))
95
aavv__wwoorrdd__sspplliittttaabbllee__33 ((_t_y_p_e_1,, _t_y_p_e_2,, _t_y_p_e_3))
96
aavv__wwoorrdd__sspplliittttaabbllee__44 ((_t_y_p_e_1,, _t_y_p_e_2,, _t_y_p_e_3,, _t_y_p_e_4))
97
For a struct with three slots
98
ssttrruucctt {{ _t_y_p_e_1 _i_d_1;; _t_y_p_e_2 _i_d_2;; _t_y_p_e_3 _i_d_3;; }}
99
you can specify _s_p_l_i_t_t_a_b_l_e as aavv__wwoorrdd__sspplliittttaabbllee__33 ((_t_y_p_e_1,,
100
_t_y_p_e_2,, _t_y_p_e_3)) .
102
(4) Push the arguments on to the list in order. Again
103
there is a macro for each simple built-in type, and
104
the macros for structure and pointer arguments
105
require an extra type argument:
107
aavv__iinntt ((_a_l_i_s_t,, _i_n_t___v_a_l_u_e));;
109
aavv__ddoouubbllee ((_a_l_i_s_t,, _d_o_u_b_l_e___v_a_l_u_e));;
111
aavv__ssttrruucctt ((_a_l_i_s_t,, _s_t_r_u_c_t___o_r___u_n_i_o_n___t_y_p_e,, _s_t_r_u_c_t___v_a_l_u_e));;
113
aavv__ppttrr ((_a_l_i_s_t,, _p_o_i_n_t_e_r___t_y_p_e,, _p_o_i_n_t_e_r___v_a_l_u_e));;
115
(5) Call the function, set the return value, and tidy
118
aavv__ccaallll ((_a_l_i_s_t));;
122
(1) Functions whose first declaration is in Kernighan &
123
Ritchie style (i.e., without a typed argument list) MUST
124
use default K&R C expression promotions (char and short to
125
int, float to double) whether they are compiled by a K&R
126
or an ANSI compiler, because the true argument types may
139
not be known at the call point. Such functions typically
140
back-convert their arguments to the declared types on
141
function entry. (In fact, the only way to pass a true
142
char, short or float in K&R C is by an explicit cast:
143
ffuunncc((((cchhaarr))cc,,((ffllooaatt))ff)) ). Similarly, some K&R compilers
144
(such as Sun cc on the sparc) actually return a float as a
147
Hence, for arguments of functions declared in K&R style
148
you should use aavv__iinntt(()) and aavv__ddoouubbllee(()) rather than
149
aavv__cchhaarr(()),, aavv__sshhoorrtt(()) or aavv__ffllooaatt(()).. If you use a K&R
150
compiler, the avcall header files may be able to detect
151
this and define aavv__ffllooaatt(()),, etc, appropriately, but with
152
an ANSI compiler there is no way _a_v_c_a_l_l can know how a
153
function was declared, so you have to correct the argument
156
(2) The explicit type arguments of the aavv__ssttrruucctt(()) and
157
aavv__ppttrr(()) macros are typically used to calculate size,
158
alignment, and passing conventions. This may not be suf-
159
ficient for some machines with unusual structure and
160
pointer handling: in this case additional aavv__ssttaarrtt___t_y_p_e(())
161
and aavv___t_y_p_e(()) macros may be defined.
163
(3) The macros aavv__ssttaarrtt__lloonngglloonngg(()), aavv__ssttaarrtt__uulloonngglloonngg(()),
164
aavv__lloonngglloonngg(()) and aavv__uulloonngglloonngg(()) work only if the C com-
165
piler has a working lloonngg lloonngg 64-bit integer type.
167
(4) The struct types used in aavv__ssttaarrtt__ssttrruucctt(()) and
168
aavv__ssttrruucctt(()) must only contain (signed or unsigned) int,
169
long, long long or pointer fields. Struct types contain-
170
ing (signed or unsigned) char, short, float, double or
171
other structs are not supported.
175
ssttddaarrgg(3), vvaarraarrggss(3).
179
The current implementations have been tested on a selec-
180
tion of common cases but there are probably still many
183
There are typically built-in limits on the size of the
184
argument-list, which may also include the size of any
187
The decision whether a struct is to be returned in regis-
188
ters or in memory considers only the struct's size and
189
alignment. This is inaccurate: for example, gcc on m68k-
190
next returns ssttrruucctt {{ cchhaarr aa,,bb,,cc;; }} in registers and
191
ssttrruucctt {{ cchhaarr aa[[33]];; }} in memory, although both types have
192
the same size and the same alignment.
206
All information is passed in CPU registers and the stack.
207
The aavvccaallll package is therefore multithread-safe.
210
PPOORRTTIINNGG AAVVCCAALLLL
211
Ports, bug-fixes, and suggestions are most welcome. The
212
macros required for argument pushing are pretty grungy,
213
but it does seem to be possible to port avcall to a range
214
of machines. Ports to non-standard or non-32-bit machines
215
are especially welcome so we can sort the interface out
216
before it's too late.
218
Knowledge about argument passing conventions can be found
219
in the gcc source, file gcc-2.6.3/config/_c_p_u/_c_p_u.h, sec-
220
tion "Stack layout; function entry, exit and calling."
222
Some of the grunge is usually handled by a C or assembly
223
level glue routine that actually pushes the arguments,
224
calls the function and unpacks any return value. This is
225
called __builtin_avcall(). A precompiled assembler version
226
for people without gcc is also made available. The routine
227
should ideally have flags for the passing conventions of
230
Many of the current routines waste a lot of stack space
231
and generally do hairy things to stack frames - a bit more
232
assembly code would probably help things along quite a bit
237
Bill Triggs <Bill.Triggs@inrialpes.fr>.
240
AACCKKNNOOWWLLEEDDGGEEMMEENNTTSS
241
Some initial ideas were stolen from the C interface to the
242
Zelk extensions to Oliver Laumann's Elk scheme interpreter
243
by J.P.Lewis, NEC C&C Research, <zilla@ccrl.nj.nec.com>
244
(for Sun4 & SGI), and Roy Featherstone's
245
<roy@robots.oxford.ac.uk> personal C interface library for
246
Sun[34] & SGI. I also looked at the machine-dependent
247
parts of the GCC and GDB distributions, and put the gcc
248
asm() extensions to good use. Thanks guys!
250
This work was partly supported by EC-ESPRIT Basic Research