1AVCALL(3) Library Functions Manual AVCALL(3)
2
3
4
6 avcall - build a C argument list incrementally and call a C function on
7 it.
8
10 #include <avcall.h>
11
12 av_alist alist;
13
14 av_start_type(alist, &func [[, return_type], &return_value ]);
15
16 av_type(alist, [arg_type,] value);
17
18 av_call(alist);
19
21 This set of macros builds an argument list for a C function and calls
22 the function on it. It significantly reduces the amount of `glue' code
23 required for parsers, debuggers, imbedded interpreters, C extensions to
24 application programs and other situations where collections of func‐
25 tions need to be called on lists of externally-supplied arguments.
26
27 Function calling conventions differ considerably on different machines
28 and avcall attempts to provide some degree of isolation from such
29 architecture dependencies.
30
31 The interface is like stdarg(3) in reverse. All of the macros return 0
32 for success, < 0 for failure (e.g., argument list overflow or type-not-
33 supported).
34
35 (1) #include <avcall.h>
36 and declare the argument list structure
37 av_alist alist;
38
39 (2) Set any special flags. This is architecture and compiler depen‐
40 dent. Compiler options that affect passing conventions may need
41 to be flagged by #defines before the #include <avcall.h> state‐
42 ment. However, the configure script should have determined which
43 #defines are needed and put them at the top of avcall.h.
44
45 (3) Initialize the alist with the function address and return value
46 pointer (if any). There is a separate macro for each simple
47 return type ([u]char, [u]short, [u]int, [u]long, [u]longlong,
48 float, double, where `u' indicates `unsigned'). The macros for
49 functions returning structures or pointers require an explicit
50 type argument.
51
52 E.g.,
53
54 av_start_int (alist, &func, &int_return);
55
56 av_start_double (alist, &func, &double_return);
57
58 av_start_void (alist, &func);
59
60 av_start_struct (alist, &func, struct_type, splittable,
61 &struct_return);
62
63 av_start_ptr (alist, &func, pointer_type,
64 &pointer_return);
65
66 The splittable flag specifies whether the struct_type can be returned
67 in registers such that every struct field fits entirely in a single
68 register. This needs to be specified for structs of size
69 2*sizeof(long). For structs of size <= sizeof(long), splittable is
70 ignored and assumed to be 1. For structs of size > 2*sizeof(long),
71 splittable is ignored and assumed to be 0. There are some handy macros
72 for this:
73 av_word_splittable_1 (type1)
74 av_word_splittable_2 (type1, type2)
75 av_word_splittable_3 (type1, type2, type3)
76 av_word_splittable_4 (type1, type2, type3, type4)
77 For a struct with three slots
78 struct { type1 id1; type2 id2; type3 id3; }
79 you can specify splittable as av_word_splittable_3 (type1, type2,
80 type3) .
81
82 (4) Push the arguments on to the list in order. Again there is a
83 macro for each simple built-in type, and the macros for struc‐
84 ture and pointer arguments require an extra type argument:
85
86 av_int (alist, int_value);
87
88 av_double (alist, double_value);
89
90 av_struct (alist, struct_or_union_type, struct_value);
91
92 av_ptr (alist, pointer_type, pointer_value);
93
94 (5) Call the function, set the return value, and tidy up:
95
96 av_call (alist);
97
98
100 (1) Functions whose first declaration is in Kernighan & Ritchie style
101 (i.e., without a typed argument list) MUST use default K&R C expression
102 promotions (char and short to int, float to double) whether they are
103 compiled by a K&R or an ANSI compiler, because the true argument types
104 may not be known at the call point. Such functions typically back-con‐
105 vert their arguments to the declared types on function entry. (In fact,
106 the only way to pass a true char, short or float in K&R C is by an
107 explicit cast: func((char)c,(float)f) ). Similarly, some K&R compilers
108 (such as Sun cc on the sparc) actually return a float as a double.
109
110 Hence, for arguments of functions declared in K&R style you should use
111 av_int() and av_double() rather than av_char(), av_short() or
112 av_float(). If you use a K&R compiler, the avcall header files may be
113 able to detect this and define av_float(), etc, appropriately, but with
114 an ANSI compiler there is no way avcall can know how a function was
115 declared, so you have to correct the argument types yourself.
116
117 (2) The explicit type arguments of the av_struct() and av_ptr() macros
118 are typically used to calculate size, alignment, and passing conven‐
119 tions. This may not be sufficient for some machines with unusual
120 structure and pointer handling: in this case additional av_start_type()
121 and av_type() macros may be defined.
122
123 (3) The macros av_start_longlong(), av_start_ulonglong(), av_longlong()
124 and av_ulonglong() work only if the C compiler has a working long long
125 64-bit integer type.
126
127 (4) The struct types used in av_start_struct() and av_struct() must
128 only contain (signed or unsigned) int, long, long long or pointer
129 fields. Struct types containing (signed or unsigned) char, short,
130 float, double or other structs are not supported.
131
132
134 stdarg(3), varargs(3).
135
136
138 The current implementations have been tested on a selection of common
139 cases but there are probably still many bugs.
140
141 There are typically built-in limits on the size of the argument-list,
142 which may also include the size of any structure arguments.
143
144 The decision whether a struct is to be returned in registers or in mem‐
145 ory considers only the struct's size and alignment. This is inaccurate:
146 for example, gcc on m68k-next returns struct { char a,b,c; } in regis‐
147 ters and struct { char a[3]; } in memory, although both types have the
148 same size and the same alignment.
149
150
152 All information is passed in CPU registers and the stack. The avcall
153 package is therefore multithread-safe.
154
155
157 Ports, bug-fixes, and suggestions are most welcome. The macros required
158 for argument pushing are pretty grungy, but it does seem to be possible
159 to port avcall to a range of machines. Ports to non-standard or
160 non-32-bit machines are especially welcome so we can sort the interface
161 out before it's too late.
162
163 Knowledge about argument passing conventions can be found in the gcc
164 source, file gcc-2.6.3/config/cpu/cpu.h, section "Stack layout; func‐
165 tion entry, exit and calling."
166
167 Some of the grunge is usually handled by a C or assembly level glue
168 routine that actually pushes the arguments, calls the function and
169 unpacks any return value. This is called avcall_call(). A precompiled
170 assembler version for people without gcc is also made available. The
171 routine should ideally have flags for the passing conventions of other
172 compilers.
173
174 Many of the current routines waste a lot of stack space and generally
175 do hairy things to stack frames - a bit more assembly code would proba‐
176 bly help things along quite a bit here.
177
178
180 Bill Triggs <Bill.Triggs@inrialpes.fr>.
181
182
184 Some initial ideas were stolen from the C interface to the Zelk exten‐
185 sions to Oliver Laumann's Elk scheme interpreter by J.P.Lewis, NEC C&C
186 Research, <zilla@ccrl.nj.nec.com> (for Sun4 & SGI), and Roy Feather‐
187 stone's <roy@robots.oxford.ac.uk> personal C interface library for
188 Sun[34] & SGI. I also looked at the machine-dependent parts of the GCC
189 and GDB distributions, and put the gcc asm() extensions to good use.
190 Thanks guys!
191
192 This work was partly supported by EC-ESPRIT Basic Research Action SEC‐
193 OND.
194
195
196
197
198 23 July 2017 AVCALL(3)