From 36f3fb91412a6f10bd2c6dde01f4d7afa1f2f2c0 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 5 Oct 2015 10:20:05 -0600 Subject: [PATCH 1/7] Add missing "@" to @var{} --- doc/libffi.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/libffi.texi b/doc/libffi.texi index b9887a8c..054fdb7e 100644 --- a/doc/libffi.texi +++ b/doc/libffi.texi @@ -152,7 +152,7 @@ If the function being called is variadic (varargs) then @code{ffi_prep_cif_var} must be used instead of @code{ffi_prep_cif}. @findex ffi_prep_cif_var -@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi var{abi}, unsigned int @var{nfixedargs}, unsigned int var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) +@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi @var{abi}, unsigned int @var{nfixedargs}, unsigned int @var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) This initializes @var{cif} according to the given parameters for a call to a variadic function. In general it's operation is the same as for @code{ffi_prep_cif} except that: From 0ebde2d24a3deb7b0cdf5cb1e625b55af2834fde Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 6 Oct 2015 11:42:43 -0600 Subject: [PATCH 2/7] document that there must be ntotalargs types --- doc/libffi.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/libffi.texi b/doc/libffi.texi index b9887a8c..56068895 100644 --- a/doc/libffi.texi +++ b/doc/libffi.texi @@ -161,7 +161,7 @@ same as for @code{ffi_prep_cif} except that: variadic arguments. It must be greater than zero. @var{ntotalargs} the total number of arguments, including variadic -and fixed arguments. +and fixed arguments. @var{argtypes} must have this many elements. Note that, different cif's must be prepped for calls to the same function when different numbers of arguments are passed. From ff33ddd1abe72b6d02d2769c0379b06eb7dbb931 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sat, 7 Nov 2015 11:45:04 -0700 Subject: [PATCH 3/7] mark ffi_prep_closure as deprecated --- include/ffi.h.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/ffi.h.in b/include/ffi.h.in index c43d52fd..b07ca855 100644 --- a/include/ffi.h.in +++ b/include/ffi.h.in @@ -337,7 +337,8 @@ ffi_status ffi_prep_closure (ffi_closure*, ffi_cif *, void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data); + void *user_data) + __attribute__((deprecated ("use ffi_prep_closure_loc instead"))); ffi_status ffi_prep_closure_loc (ffi_closure*, From 473bcbcad32e9e320a7a5c111cefd0d8ad570245 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Sat, 7 Nov 2015 12:01:06 -0700 Subject: [PATCH 4/7] documentation fixes Fixes #78. Documentation for #33 and #35, but no fix. --- doc/libffi.texi | 188 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 181 insertions(+), 7 deletions(-) diff --git a/doc/libffi.texi b/doc/libffi.texi index ff72e583..125d33d3 100644 --- a/doc/libffi.texi +++ b/doc/libffi.texi @@ -107,6 +107,7 @@ values passed between the two languages. * Multiple ABIs:: Different passing styles on one platform. * The Closure API:: Writing a generic function. * Closure Example:: A closure example. +* Thread Safety:: Thread safety. @end menu @@ -172,6 +173,10 @@ Also note that a call to @code{ffi_prep_cif_var} with @end defun +Note that the resulting @code{ffi_cif} holds pointers to all the +@code{ffi_type} objects that were used durin initialization. You must +ensure that these type objects have a lifetime at least as long as +that of the @code{ffi_cif}. To call a function using an initialized @code{ffi_cif}, use the @code{ffi_call} function: @@ -190,12 +195,29 @@ to ensure this. If @var{cif} declares that the function returns @code{void} (using @code{ffi_type_void}), then @var{rvalue} is ignored. +In most situations, @samp{libffi} will handle promotion according to +the ABI. However, for historical reasons, there is a special case +with return values that must be handled by your code. In particular, +for integral (not @code{struct}) types that are narrower than the +system register size, the return value will be widened by +@samp{libffi}. @samp{libffi} provides a type, @code{ffi_arg}, that +can be used as the return type. For example, if the CIF was defined +with a return type of @code{char}, @samp{libffi} will try to store a +full @code{ffi_arg} into the return value. + @var{avalues} is a vector of @code{void *} pointers that point to the memory locations holding the argument values for a call. If @var{cif} declares that the function has no arguments (i.e., @var{nargs} was 0), then @var{avalues} is ignored. Note that argument values may be modified by the callee (for instance, structs passed by value); the burden of copying pass-by-value arguments is placed on the caller. + +Note that while the return value must be register-sized, arguments +should exactly match their declared type. For example, if an argument +is a @code{short}, then the entry is @var{avalues} should point to an +object declared as @code{short}; but if the return type is +@code{short}, then @var{rvalue} should point to an object declared as +a larger type -- usually @code{ffi_arg}. @end defun @@ -246,6 +268,8 @@ int main() @menu * Primitive Types:: Built-in types. * Structures:: Structure types. +* Size and Alignment:: Size and alignment of types. +* Arrays and Unions:: Arrays and unions. * Type Example:: Structure type example. * Complex:: Complex types. * Complex Type Example:: Complex type example. @@ -370,8 +394,7 @@ when passing to @code{ffi_prep_cif}. @node Structures @subsection Structures -Although @samp{libffi} has no special support for unions or -bit-fields, it is perfectly happy passing structures back and forth. +@samp{libffi} is perfectly happy passing structures back and forth. You must first describe the structure to @samp{libffi} by creating a new @code{ffi_type} object for it. @@ -391,9 +414,132 @@ For a structure, this should be set to @code{FFI_TYPE_STRUCT}. @item ffi_type **elements This is a @samp{NULL}-terminated array of pointers to @code{ffi_type} objects. There is one element per field of the struct. + +Note that @samp{libffi} has no special support for bit-fields. You +must manage these manually. @end table @end deftp +The @code{size} and @code{alignment} fields will be filled in by +@code{ffi_prep_cif} or @code{ffi_prep_cif_var}, as needed. + +@node Size and Alignment +@subsection Size and Alignment + +@code{libffi} will set the @code{size} and @code{alignment} fields of +an @code{ffi_type} object for you. It does so using its knowledge of +the ABI. + +You might expect that you can simply read these fields for a type that +has been laid out by @code{libffi}. However, there are some caveats. + +@itemize @bullet +@item +The size or alignment of some of the built-in types may vary depending +on the chosen ABI. + +@item +The size and alignment of a new structure type will not be set by +@code{libffi} until it has been passed to @code{ffi_prep_cif}. + +@item +A structure type cannot be shared across ABIs. Instead each ABI needs +its own copy of the structure type. +@end itemize + +So, before examining these fields, it is safest to pass the +@code{ffi_type} object to @code{ffi_prep_cif} first. This function +will do all the needed setup. + +@example +ffi_type *desired_type; +ffi_abi desired_abi; +@dots{} +ffi_cif cif; +if (ffi_prep_cif (&cif, desired_abi, 0, desired_type, NULL) == FFI_OK) + @{ + size_t size = desired_type->size; + unsigned short alignment = desired_type->alignment; + @} +@end example + +@node Arrays and Unions +@subsection Arrays and Unions + +@subsubsection Arrays + +@samp{libffi} does not have direct support for arrays or unions. +However, they can be emulated using structures. + +To emulate an array, simply create an @code{ffi_type} using +@code{FFI_TYPE_STRUCT} with as many members as there are elements in +the array. + +@example +ffi_type array_type; +ffi_type **elements +int i; + +elements = malloc ((n + 1) * sizeof (ffi_type *)); +for (i = 0; i < n; ++i) + elements[i] = array_element_type; +elements[n] = NULL; + +array_type.size = array_type.alignment = 0; +array_type.type = FFI_TYPE_STRUCT; +array_type.elements = elements; +@end example + +Note that arrays cannot be passed or returned by value in C -- +structure types created like this should only be used to refer to +members of real @code{FFI_TYPE_STRUCT} objects. + +However, a phony array type like this will not cause any errors from +@samp{libffi} if you use it as an argument or return type. This may +be confusing. + +@subsubsection Unions + +A union can also be emulated using @code{FFI_TYPE_STRUCT}. In this +case, however, you must make sure that the size and alignment match +the real requirements of the union. + +One simple way to do this is to ensue that each element type is laid +out. Then, give the new structure type a single element; the size of +the largest element; and the largest alignment seen as well. + +This example uses the @code{ffi_prep_cif} trick to ensure that each +element type is laid out. + +@example +ffi_abi desired_abi; +ffi_type union_type; +ffi_type **union_elements; + +int i; +ffi_type element_types[2]; + +element_types[1] = NULL; + +union_type.size = union_type.alignment = 0; +union_type.type = FFI_TYPE_STRUCT; +union_type.elements = element_types; + +for (i = 0; union_elements[i]; ++i) + @{ + ffi_cif cif; + if (ffi_prep_cif (&cif, desired_abi, 0, union_elements[i], NULL) == FFI_OK) + @{ + if (union_elements[i]->size > union_type.size) + @{ + union_type.size = union_elements[i]; + size = union_elements[i]->size; + @} + if (union_elements[i]->alignment > union_type.alignment) + union_type.alignment = union_elements[i]->alignment; + @} + @} +@end example @node Type Example @subsection Type Example @@ -636,6 +782,8 @@ Prepare a closure function. the writable address returned by @code{ffi_closure_alloc}. @var{cif} is the @code{ffi_cif} describing the function parameters. +Note that this object, and the types to which it refers, must be kept +alive until the closure itself is freed. @var{user_data} is an arbitrary datum that is passed, uninterpreted, to your closure function. @@ -652,8 +800,12 @@ The @code{ffi_cif} passed to @code{ffi_prep_closure_loc}. @item ret A pointer to the memory used for the function's return value. @var{fun} must fill this, unless the function is declared as returning -@code{void}. +@code{void}. Note that this points to memory that is exactly the size +of the type given as the return type when initializing the CIF. In +particular, closures do not have the special promotion behavior of +@code{ffi_call}. @c FIXME: is this NULL for void-returning functions? +@c (experimentally it is not, but it seems like a good idea) @item args A vector of pointers to memory holding the arguments to the function. @@ -664,8 +816,7 @@ The same @var{user_data} that was passed to @end table @code{ffi_prep_closure_loc} will return @code{FFI_OK} if everything -went ok, and something else on error. -@c FIXME: what? +went ok, and one of the other @code{ffi_status} values on error. After calling @code{ffi_prep_closure_loc}, you can cast @var{codeloc} to the appropriate pointer-to-function type. @@ -733,6 +884,28 @@ int main() @end example +@node Thread Safety +@section Thread Safety + +@code{libffi} is not completely thread-safe. However, many parts are, +and if you follow some simple rules, you can use it safely in a +multi-threaded program. + +@itemize @bullet +@item +@code{ffi_prep_cif} may modify the @code{ffi_type} objects passed to +it. It is best to ensure that only a single thread prepares a given +@code{ffi_cif} at a time. + +@item +On some platforms, @code{ffi_prep_cif} may modify the size and +alignment of some types, depending on the chosen ABI. On these +platforms, if you switch between ABIs, you must ensure that there is +only one call to @code{ffi_prep_cif} at a time. + +Currently the only affected platform is PowerPC and the only affected +type is @code{long double}. +@end itemize @node Missing Features @chapter Missing Features @@ -749,9 +922,10 @@ There is no support for bit fields in structures. @item The ``raw'' API is undocumented. -@c argument promotion? -@c unions? @c anything else? + +@item +The Go API is undocumented. @end itemize Note that variadic support is very new and tested on a relatively From 88deacdd4220b66805b6ad10abd61fa3640afb67 Mon Sep 17 00:00:00 2001 From: Anthony Green Date: Sun, 15 Nov 2015 08:39:17 -0500 Subject: [PATCH 5/7] speling fix --- doc/libffi.texi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/libffi.texi b/doc/libffi.texi index 125d33d3..0459899c 100644 --- a/doc/libffi.texi +++ b/doc/libffi.texi @@ -174,9 +174,9 @@ Also note that a call to @code{ffi_prep_cif_var} with @end defun Note that the resulting @code{ffi_cif} holds pointers to all the -@code{ffi_type} objects that were used durin initialization. You must -ensure that these type objects have a lifetime at least as long as -that of the @code{ffi_cif}. +@code{ffi_type} objects that were used during initialization. You +must ensure that these type objects have a lifetime at least as long +as that of the @code{ffi_cif}. To call a function using an initialized @code{ffi_cif}, use the @code{ffi_call} function: From 8a7cdeb0412f9ef8bbe0a7833d662dbec40b472f Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 17 Dec 2015 16:51:32 -0700 Subject: [PATCH 6/7] fix formatting of ffi_prep_closure_loc arguments --- doc/libffi.texi | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/doc/libffi.texi b/doc/libffi.texi index 0459899c..4f6512f9 100644 --- a/doc/libffi.texi +++ b/doc/libffi.texi @@ -776,23 +776,30 @@ the closure function: @findex ffi_prep_closure_loc @defun ffi_status ffi_prep_closure_loc (ffi_closure *@var{closure}, ffi_cif *@var{cif}, void (*@var{fun}) (ffi_cif *@var{cif}, void *@var{ret}, void **@var{args}, void *@var{user_data}), void *@var{user_data}, void *@var{codeloc}) -Prepare a closure function. +Prepare a closure function. The arguments to +@code{ffi_prep_closure_loc} are: -@var{closure} is the address of a @code{ffi_closure} object; this is -the writable address returned by @code{ffi_closure_alloc}. +@table @var +@item closure +The address of a @code{ffi_closure} object; this is the writable +address returned by @code{ffi_closure_alloc}. -@var{cif} is the @code{ffi_cif} describing the function parameters. -Note that this object, and the types to which it refers, must be kept -alive until the closure itself is freed. +@item cif +The @code{ffi_cif} describing the function parameters. Note that this +object, and the types to which it refers, must be kept alive until the +closure itself is freed. -@var{user_data} is an arbitrary datum that is passed, uninterpreted, -to your closure function. +@item user_data +An arbitrary datum that is passed, uninterpreted, to your closure +function. -@var{codeloc} is the executable address returned by -@code{ffi_closure_alloc}. +@item codeloc +The executable address returned by @code{ffi_closure_alloc}. + +@item fun +The function which will be called when the closure is invoked. It is +called with the arguments: -@var{fun} is the function which will be called when the closure is -invoked. It is called with the arguments: @table @var @item cif The @code{ffi_cif} passed to @code{ffi_prep_closure_loc}. @@ -814,6 +821,7 @@ A vector of pointers to memory holding the arguments to the function. The same @var{user_data} that was passed to @code{ffi_prep_closure_loc}. @end table +@end table @code{ffi_prep_closure_loc} will return @code{FFI_OK} if everything went ok, and one of the other @code{ffi_status} values on error. From 6affad79111c45982fd29637a46bc756abb128a3 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 17 Dec 2015 16:58:10 -0700 Subject: [PATCH 7/7] correctly document closure return promotion --- doc/libffi.texi | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/doc/libffi.texi b/doc/libffi.texi index 4f6512f9..87a4f50c 100644 --- a/doc/libffi.texi +++ b/doc/libffi.texi @@ -806,13 +806,17 @@ The @code{ffi_cif} passed to @code{ffi_prep_closure_loc}. @item ret A pointer to the memory used for the function's return value. -@var{fun} must fill this, unless the function is declared as returning -@code{void}. Note that this points to memory that is exactly the size -of the type given as the return type when initializing the CIF. In -particular, closures do not have the special promotion behavior of -@code{ffi_call}. -@c FIXME: is this NULL for void-returning functions? -@c (experimentally it is not, but it seems like a good idea) + +If the function is declared as returning @code{void}, then this value +is garbage and should not be used. + +Otherwise, @var{fun} must fill the object to which this points, +following the same special promotion behavior as @code{ffi_call}. +That is, in most cases, @var{ret} points to an object of exactly the +size of the type specified when @var{cif} was constructed. However, +integral types narrower than the system register size are widened. In +these cases your program may assume that @var{ret} points to an +@code{ffi_arg} object. @item args A vector of pointers to memory holding the arguments to the function.