comparison dyncall/dyncall.3 @ 533:71c884e610f0

- integration of patches from Raphael Luba, Thekla, Inc.: * integration of aggregate-by-value (struct, union) support patch for x64 (win and sysv) * windows/x64 asm additions to specify how stack unwinds (help for debuggers, exception handling, etc.) * see Changelog for details - new calling convention modes for thiscalls (platform agnostic, was specific before) * new signature character for platform agnostic thiscalls ('*' / DC_SIGCHAR_CC_THISCALL) - dcCallF(), dcVCallF(), dcArgF() and dcVArgF(): * added support for aggregates-by-value (wasn't part of patch) * change that those functions don't implicitly call dcReset() anymore, which was unflexible (breaking change) - added macros to feature test implementation for aggregate-by-value and syscall support - changed libdyncall_s.lib and libdyncallback_s.lib order in callback test makefiles, as some toolchains are picky about order - doc: * man page updates to describe aggregate interface * manual overview changes to highlight platforms with aggregate-by-value support - test/plain: replaced tests w/ old/stale sctruct interface with new aggregate one
author Tassilo Philipp
date Thu, 21 Apr 2022 13:35:47 +0200
parents 78dfa2f9783a
children 52e87d4988e3
comparison
equal deleted inserted replaced
532:d4bf63ab9164 533:71c884e610f0
1 .\" Copyright (c) 2007-2020 Daniel Adler <dadler AT uni-goettingen DOT de>, 1 .\" Copyright (c) 2007-2022 Daniel Adler <dadler AT uni-goettingen DOT de>,
2 .\" Tassilo Philipp <tphilipp AT potion-studios DOT com> 2 .\" Tassilo Philipp <tphilipp AT potion-studios DOT com>
3 .\" 3 .\"
4 .\" Permission to use, copy, modify, and distribute this software for any 4 .\" Permission to use, copy, modify, and distribute this software for any
5 .\" purpose with or without fee is hereby granted, provided that the above 5 .\" purpose with or without fee is hereby granted, provided that the above
6 .\" copyright notice and this permission notice appear in all copies. 6 .\" copyright notice and this permission notice appear in all copies.
45 .Fn dcArgFloat "DCCallVM * vm" "DCfloat arg" 45 .Fn dcArgFloat "DCCallVM * vm" "DCfloat arg"
46 .Ft void 46 .Ft void
47 .Fn dcArgDouble "DCCallVM * vm" "DCdouble arg" 47 .Fn dcArgDouble "DCCallVM * vm" "DCdouble arg"
48 .Ft void 48 .Ft void
49 .Fn dcArgPointer "DCCallVM * vm" "DCpointer arg" 49 .Fn dcArgPointer "DCCallVM * vm" "DCpointer arg"
50 .Ft void
51 .Fn dcArgAggr "DCCallVM * vm" "const DCaggr * ag" "const void * value"
50 .Ft DCvoid 52 .Ft DCvoid
51 .Fn dcCallVoid "DCCallVM * vm" "DCpointer funcptr" 53 .Fn dcCallVoid "DCCallVM * vm" "DCpointer funcptr"
52 .Ft DCbool 54 .Ft DCbool
53 .Fn dcCallBool "DCCallVM * vm" "DCpointer funcptr" 55 .Fn dcCallBool "DCCallVM * vm" "DCpointer funcptr"
54 .Ft DCchar 56 .Ft DCchar
65 .Fn dcCallFloat "DCCallVM * vm" "DCpointer funcptr" 67 .Fn dcCallFloat "DCCallVM * vm" "DCpointer funcptr"
66 .Ft DCdouble 68 .Ft DCdouble
67 .Fn dcCallDouble "DCCallVM * vm" "DCpointer funcptr" 69 .Fn dcCallDouble "DCCallVM * vm" "DCpointer funcptr"
68 .Ft DCpointer 70 .Ft DCpointer
69 .Fn dcCallPointer "DCCallVM * vm" "DCpointer funcptr" 71 .Fn dcCallPointer "DCCallVM * vm" "DCpointer funcptr"
72 .Ft DCpointer
73 .Fn dcCallAggr "DCCallVM * vm" "DCpointer funcptr" "const DCaggr * ag" "DCpointer ret"
74 .Ft void
75 .Fn dcBeginCallAggr "DCCallVM * vm" "const DCaggr * ag"
70 .Ft void 76 .Ft void
71 .Fn dcArgF "DCCallVM * vm" "const DCsigchar * signature" "..." 77 .Fn dcArgF "DCCallVM * vm" "const DCsigchar * signature" "..."
72 .Ft void 78 .Ft void
73 .Fn dcVArgF "DCCallVM * vm" "const DCsigchar * signature" "va_list args" 79 .Fn dcVArgF "DCCallVM * vm" "const DCsigchar * signature" "va_list args"
74 .Ft void 80 .Ft void
75 .Fn dcCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "..." 81 .Fn dcCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "..."
76 .Ft void 82 .Ft void
77 .Fn dcVCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "va_list args" 83 .Fn dcVCallF "DCCallVM * vm" "DCValue * result" "DCpointer funcptr" "const DCsigchar * signature" "va_list args"
84 .Ft DCaggr*
85 .Fn dcNewAggr "DCsize maxFieldCount" "DCsize size"
86 .Ft void
87 .Fn dcAggrField "DCaggr* ag" "DCsigchar type" "DCint offset" "DCsize array_len" "..."
88 .Ft void
89 .Fn dcCloseAggr "DCaggr* ag"
90 .Ft void
91 .Fn dcFreeAggr "DCaggr* ag"
78 .Sh DESCRIPTION 92 .Sh DESCRIPTION
79 The 93 The
80 .Nm 94 .Nm
81 library encapsulates architecture-, OS- and compiler-specific function call 95 library encapsulates architecture-, OS- and compiler-specific function call
82 semantics in a virtual "bind argument parameters from left to right and then 96 semantics in a virtual "bind argument parameters from left to right and then
93 and then used to actually invoke the call, is called CallVM. It is possible to 107 and then used to actually invoke the call, is called CallVM. It is possible to
94 change the calling convention used by the CallVM at run-time. Due to the fact 108 change the calling convention used by the CallVM at run-time. Due to the fact
95 that nearly every platform comes with one or more distinct calling conventions, the 109 that nearly every platform comes with one or more distinct calling conventions, the
96 .Nm 110 .Nm
97 library project intends to be a portable and open-source approach to the variety of 111 library project intends to be a portable and open-source approach to the variety of
98 compiler-specific binary interfaces, platform specific subtleties, and so on... 112 compiler/toolchain/platform-specific binary interfaces subtleties, and so on...
99 .Pp 113 .Pp
100 .Fn dcNewCallVM 114 .Fn dcNewCallVM
101 creates a new CallVM object, where 115 creates a new CallVM object, where
102 .Ar size 116 .Ar size
103 specifies the max size of the internal stack that will be allocated and used to 117 specifies the max size of the internal stack that will be allocated and used to
111 sense (e.g. using a PowerPC calling convention on a MIPS platform) and are 125 sense (e.g. using a PowerPC calling convention on a MIPS platform) and are
112 silently ignored. 126 silently ignored.
113 .Pp 127 .Pp
114 .Fn dcReset 128 .Fn dcReset
115 resets the internal stack of arguments and prepares it for a new call. This 129 resets the internal stack of arguments and prepares it for a new call. This
116 function should be called after setting the call mode (using dcMode), but prior 130 function should be called after setting the initial/main call mode (using
117 to binding arguments to the CallVM (except for when setting mode 131 dcMode()), but prior to binding arguments to the CallVM (sometimes dcMode()
118 DC_SIGCHAR_CC_ELLIPSIS_VARARGS, which is used prior to binding varargs of 132 calls are needed after pushing some args, e.g. DC_SIGCHAR_CC_ELLIPSIS_VARARGS,
119 variadic functions). Use it also when reusing a CallVM, as arguments don't get 133 which is used prior to binding varargs of variadic functions). Use it also when
120 flushed automatically after a function call invocation. Note: you should also 134 reusing a CallVM, as arguments don't get flushed automatically after a function
121 call this function after initial creation of the a CallVM object, as 135 call invocation. Note: you should also call this function after initial
122 dcNewCallVM doesn't do this, implicitly. 136 creation of the a CallVM object, as dcNewCallVM doesn't do this, implicitly.
123 .Pp 137 .Pp
124 .Fn dcArgBool , 138 .Fn dcArgBool ,
125 .Fn dcArgChar , 139 .Fn dcArgChar ,
126 .Fn dcArgShort , 140 .Fn dcArgShort ,
127 .Fn dcArgInt , 141 .Fn dcArgInt ,
128 .Fn dcArgLong , 142 .Fn dcArgLong ,
129 .Fn dcArgLongLong , 143 .Fn dcArgLongLong ,
130 .Fn dcArgFloat , 144 .Fn dcArgFloat ,
131 .Fn dcArgDouble 145 .Fn dcArgDouble ,
146 .Fn dcArgPointer
132 and 147 and
133 .Fn dcArgPointer 148 .Fn dcArgAggr
134 are used to bind arguments of the named types to the CallVM object. Arguments should 149 are used to bind arguments of the named types to the CallVM object. Arguments should
135 be bound in 150 be bound in
136 .Em "left to right" 151 .Em "left to right"
137 order regarding the C function prototype. 152 order regarding the C function prototype.
138 .Pp 153 .Pp
142 .Fn dcCallShort , 157 .Fn dcCallShort ,
143 .Fn dcCallInt , 158 .Fn dcCallInt ,
144 .Fn dcCallLong , 159 .Fn dcCallLong ,
145 .Fn dcCallLongLong , 160 .Fn dcCallLongLong ,
146 .Fn dcCallFloat , 161 .Fn dcCallFloat ,
147 .Fn dcCallDouble 162 .Fn dcCallDouble ,
163 .Fn dcCallPointer
148 and 164 and
149 .Fn dcCallPointer 165 .Fn dcCallAggr
150 call the function with the bound arguments and returning the named type, where 166 call the function with the previously bound arguments and return the named
167 type, where
151 .Ar funcptr 168 .Ar funcptr
152 is a pointer to the function to call. After the invocation of the function 169 is a pointer to the function to call. After the invocation of the function
153 call, the argument values are still bound to the CallVM and a second call 170 call, the argument values are still bound to the CallVM and a second call
154 using the same arguments can be issued. Call 171 using the same arguments can be issued. Call
155 .Fn reset 172 .Fn dcReset
156 to clear the internal argument stack. 173 (as described above) to clear the internal argument stack.
174 .Pp
175 The interfaces for passing and/or returning aggregates (struct, union) by value
176 need to be explained as they are a bit more complex. Every such argument or
177 return type needs some extra info describing its layout via a
178 .Ft DCaggr
179 structure (except for non-trivial C++ aggregates, see AGGREGATE DESCRIPTION for
180 more information, below). Passing such arguments is then done by using
181 .Fn dcArgAggr ,
182 where
183 .Ar ag
184 is a pointer to the description and
185 .Ar value
186 is a pointer to the aggregate in question. Calling a function that returns an
187 aggregate by value is done via two functions,
188 .Fn dcBeginCallAggr ,
189 which handles special cases to facilitate the implementation and
190 .Sy must
191 be called
192 .Sy before
193 pushing any arguments, and finally
194 .Fn dcCallAggr
195 where
196 .Ar ag
197 is a pointer to the description (for both calls) and
198 .Ar ret
199 points to memory large enough to hold the to be returned aggregate.
200 .Fn dcCallAggr
201 returns a pointer to
202 .Ar ret .
203 .Pp
204 .Sy NOTE:
205 C++ non-trivial aggregates (check with the std::is_trivial type trait) need
206 some special handling. First of all, no aggregate description is needed and
207 NULL must be passed wherever a
208 .Ft DCaggr*
209 argument is needed. Also, as
210 .Nm
211 is oblivious to how to do any custom/non-trivial construction or copy, and thus
212 cannot do the copy of the aggregate, passed by-value, itself, the user has to
213 provide such copies, where needed. E.g. when passing such an aggregate as an
214 argument by-value, using
215 .Fn dcArgAggr ,
216 in order to preserver the call's by-value semantics.
157 .Pp 217 .Pp
158 .Fn dcArgF , 218 .Fn dcArgF ,
159 .Fn dcVArgF , 219 .Fn dcVArgF ,
160 .Fn dcCallF 220 .Fn dcCallF
161 and 221 and
162 .Fn dcVCallF 222 .Fn dcVCallF
163 can be used to bind arguments in a printf-style call, using a signature 223 can be used to bind arguments in a printf-style call, using a signature
164 string encoding the argument types and return type. The former 2 only bind 224 string encoding the argument and return types. The former 2 only bind
165 the arguments to the 225 the arguments to the
166 .Ar vm 226 .Ar vm
167 object (and ignore return types specified in the 227 object (and ignore return types specified in the
168 signature), whereas the latter two issue a call to the given function pointer, 228 signature), whereas the latter two issue a call to the given function pointer,
169 afterwards. The return value will be stored in 229 afterwards. The return value will be stored in
170 .Ar result . 230 .Ar result .
171 The signature string also features calling convention mode selection. 231 The signature string also features calling convention mode selection.
172 For information about the signature format, refer to the 232 For information about the signature format, refer to dyncall_signature.h or the
173 .Nm 233 .Nm
174 manual in PDF format. 234 manual.
235 .Pp
236 For passing aggregates using
237 .Fn dc*F
238 functions, pass two varargs for each aggregate, first a pointer to DCaggr, then
239 a pointer to the aggregate in question. For returning aggregates using those
240 functions, pass
241 .Sy two final extra
242 arguments, first a pointer to DCaggr describing the return value, then a
243 pointer to memory large enough to hold it. An explicit call do
244 .Fn dcBeginCallAggr
245 is not needed in those cases, and a pointer to the to be returned aggregate is
246 returned via
247 .Ar result .
248 .Sh AGGREGATE DESCRIPTION
249 In order to describe an aggregate (except for C++ non-trivial aggregates, as
250 mentioned above), create a DCaggr object using
251 .Fn dcNewAggr ,
252 where
253 .Ar maxFieldCount
254 is greater or equal to the number of fields the aggregate has (a nested
255 aggregate or an array is counted as one field), and
256 .Ar size
257 is the size of the aggregate (e.g. as determined by sizeof()).
258 .Pp
259 .Fn dcFreeAggr
260 destroys the DCaggr object.
261 .Pp
262 .Fn dcAggrField
263 is used to describe the aggregate, field-by-field (in order), with
264 .Ar type
265 being a DC_SIGCHAR_* (see dyncall_signature.h),
266 .Ar offset
267 being the offset of the field from the beginning of the aggregate (use C's
268 offsetof(3)), and
269 .Ar array_len
270 being the number of array elements,
271 .Sy iff
272 the field is an array, otherwise use 1. For nested aggregates (when using
273 DC_SIGCHAR_AGGREGATE as
274 .Ft type ) ,
275 one needs to pass the pointer to the nested aggregate's DCaggr object as last
276 argument (in
277 .Ar ... ) .
278 .Pp
279 Call
280 .Fn dcCloseAggr
281 after having described all fields of an aggregate.
282 .Pp
283 Note that c99 flexible array members do not count as a field, and must be
284 omitted, as passing aggregates with a flexible array member by value in C would
285 also omit it.
175 .Sh EXAMPLE 286 .Sh EXAMPLE
176 Let's say, we want to make a call to the function: 287 Let's say, we want to make a call to the function:
177 .Bd -literal -offset indent 288 .Bd -literal -offset indent
178 double sqrt(double x); 289 double sqrt(double x);
179 .Ed 290 .Ed