1AVCALL(3) Library Functions Manual AVCALL(3) 2 3 4 5[1mNAME[0m 6 avcall - build a C argument list incrementally and call a C function on 7 it. 8 9[1mSYNOPSIS[0m 10 [1m#include <avcall.h>[0m 11 12 [1mav_alist [4m[22malist[24m[1m;[0m 13 14 [1mav_start_[4m[22mtype[24m[1m([4m[22malist[24m[1m, [4m[22m&func[24m [[[1m, [4m[22mreturn_type[24m][1m, [4m[22m&return_value[24m ][1m);[0m 15 16 [1mav_[4m[22mtype[24m[1m([4m[22malist[24m[1m, [22m[[4marg_type[24m[1m,[22m] [4mvalue[24m[1m);[0m 17 18 [1mav_call([4m[22malist[24m[1m);[0m 19 20[1mDESCRIPTION[0m 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 [4mavcall[24m attempts to provide some degree of isolation from such 29 architecture dependencies. 30 31 The interface is like [1mstdarg[22m(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) [1m#include <avcall.h>[0m 36 and declare the argument list structure 37 [1mav_alist [4m[22malist[24m[1m;[0m 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 [1m#define[22ms before the [1m#include <avcall.h> [22mstate‐ 42 ment. However, the [4mconfigure[24m script should have determined which 43 [1m#define[22ms are needed and put them at the top of [1mavcall.h[22m. 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 [1mav_start_int ([4m[22malist[24m[1m, [4m[22m&func[24m[1m, [4m[22m&int_return[24m[1m);[0m 55 56 [1mav_start_double ([4m[22malist[24m[1m, [4m[22m&func[24m[1m, [4m[22m&double_return[24m[1m);[0m 57 58 [1mav_start_void ([4m[22malist[24m[1m, [4m[22m&func[24m[1m);[0m 59 60 [1mav_start_struct ([4m[22malist[24m[1m, [4m[22m&func[24m[1m, [4m[22mstruct_type[24m[1m, [4m[22msplittable[24m[1m,[0m 61 [4m&struct_return[24m[1m);[0m 62 63 [1mav_start_ptr ([4m[22malist[24m[1m, [4m[22m&func[24m[1m, [4m[22mpointer_type[24m[1m,[0m 64 [4m&pointer_return[24m[1m);[0m 65 66 The [4msplittable[24m flag specifies whether the [4mstruct_type[24m 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), [4msplittable[24m is 70 ignored and assumed to be 1. For structs of size > 2*sizeof(long), 71 [4msplittable[24m is ignored and assumed to be 0. There are some handy macros 72 for this: 73 [1mav_word_splittable_1 ([4m[22mtype1[24m[1m)[0m 74 [1mav_word_splittable_2 ([4m[22mtype1[24m[1m, [4m[22mtype2[24m[1m)[0m 75 [1mav_word_splittable_3 ([4m[22mtype1[24m[1m, [4m[22mtype2[24m[1m, [4m[22mtype3[24m[1m)[0m 76 [1mav_word_splittable_4 ([4m[22mtype1[24m[1m, [4m[22mtype2[24m[1m, [4m[22mtype3[24m[1m, [4m[22mtype4[24m[1m)[0m 77 For a struct with three slots 78 [1mstruct { [4m[22mtype1[24m [4mid1[24m[1m; [4m[22mtype2[24m [4mid2[24m[1m; [4m[22mtype3[24m [4mid3[24m[1m; }[0m 79 you can specify [4msplittable[24m as [1mav_word_splittable_3 ([4m[22mtype1[24m[1m, [4m[22mtype2[24m[1m,[0m 80 [4mtype3[24m[1m) [22m. 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 [1mav_int ([4m[22malist[24m[1m, [4m[22mint_value[24m[1m);[0m 87 88 [1mav_double ([4m[22malist[24m[1m, [4m[22mdouble_value[24m[1m);[0m 89 90 [1mav_struct ([4m[22malist[24m[1m, [4m[22mstruct_or_union_type[24m[1m, [4m[22mstruct_value[24m[1m);[0m 91 92 [1mav_ptr ([4m[22malist[24m[1m, [4m[22mpointer_type[24m[1m, [4m[22mpointer_value[24m[1m);[0m 93 94 (5) Call the function, set the return value, and tidy up: 95 96 [1mav_call ([4m[22malist[24m[1m);[0m 97 98 99[1mNOTES[0m 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: [1mfunc((char)c,(float)f) [22m). 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 [1mav_int() [22mand [1mav_double() [22mrather than [1mav_char(), av_short() [22mor 112 [1mav_float(). [22mIf you use a K&R compiler, the avcall header files may be 113 able to detect this and define [1mav_float(), [22metc, appropriately, but with 114 an ANSI compiler there is no way [4mavcall[24m 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 [1mav_struct() [22mand [1mav_ptr() [22mmacros 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 [1mav_start_[4m[22mtype[24m[1m()[0m 121 and [1mav_[4m[22mtype[24m[1m() [22mmacros may be defined. 122 123 (3) The macros [1mav_start_longlong()[22m, [1mav_start_ulonglong()[22m, [1mav_longlong()[0m 124 and [1mav_ulonglong() [22mwork only if the C compiler has a working [1mlong long[0m 125 64-bit integer type. 126 127 (4) The struct types used in [1mav_start_struct() [22mand [1mav_struct() [22mmust 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 133[1mSEE ALSO[0m 134 [1mstdarg[22m(3), [1mvarargs[22m(3). 135 136 137[1mBUGS[0m 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 [1mstruct { char a,b,c; } [22min regis‐ 147 ters and [1mstruct { char a[3]; } [22min memory, although both types have the 148 same size and the same alignment. 149 150 151[1mNON-BUGS[0m 152 All information is passed in CPU registers and the stack. The [1mavcall[0m 153 package is therefore multithread-safe. 154 155 156[1mPORTING AVCALL[0m 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/[4mcpu[24m/[4mcpu[24m.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 179[1mAUTHOR[0m 180 Bill Triggs <Bill.Triggs@inrialpes.fr>. 181 182 183[1mACKNOWLEDGEMENTS[0m 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) 199