| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (bit_s): New symbol variable.
(ffi_generic_sbit_put, ffi_generic_sbit_get,
ffi_generic_ubit_put, ffi_generic_ubit_get): New static
functions.
(bitfield_syntax_p): Include bit symbol in the check.
(make_ffi_type_pointer): Zero size is no longer an early
rejection test for bitfields; don't rely on it.
(make_ffi_type_struct): Revise the member calculating loop
to handle bitfields of various sizes. If a bitfield
follows one of a different size, it starts a new cell
even if the previous one has room, et cetera.
The masking and shifting is set up to work on cells of
int size; however, the new ffi_generic_s?bit_{put,get}
functions use a temporary buffer and transfer just the
right number of bytes to and from the actual buffer.
(ffi_struct_compile): The check against incomplete type
members only needs to test size zero; bitfields have nonzero
size now, which is the true size of the underlying storage
unit. They also have true alignment, which is used in
make_ffi_type_struct rather than hard-coding to alignof (int).
New syntax (bit width type) is now handled, where type can
be any of the signed and unsigned integral types up to int32
and int. The endian types are not supported for now.
(ffi_typedef, ffi_size, ffi_alignof): Zero size is no longer
an early rejection test for bitfields; don't rely on it.
(ffi_init): Initialize bit_s.
* ffi.h (bit_s): Declared.
* txr.1: Documented.
|
|
|
|
|
|
| |
* ffi.c (ffi_type_compile): Give the bitfield type
the evaluated syntax where the width expression
is reduced to an integer value.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Old style casts have crept into the code base.
* buf.c (make_buf, buf_grow, buf_get_i8, buf_get_u8): Replace
old style cast with macro.
* ffi.c (align_sw_get, align_sw_put, ffi_be_i32_get,
ffi_be_u32_get, ffi_le_i32_put, ffi_le_i32_get,
ffi_le_u32_get, ffi_be_i64_put, ffi_be_i64_get,
ffi_be_u64_get, ffi_le_i64_put, ffi_le_i64_get,
ffi_le_u64_get, ffi_sbit_put, ffi_sbit_get,
ffi_init_extra_types): Likewise.
* hash.c (hash_buf): Likewise.
* itypes.c (c_i32, c_i64, c_u64): Likewise.
* stream.c (stdio_put_buf, stdio_fill_buf): Likewise.
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_sbit_put, make_ffi_type_struct): Fix
signed/unsigned comparison warning from g++.
(pad_retval): Likewise.
* stream.c (stdio_put_buf, stdio_fill_buf): Likewise.
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_be_i16_rput, ffi_be_i16_rget, ffi_be_u16_rput,
ffi_be_u16_rget, ffi_be_i32_rput, ffi_be_i32_rget,
ffi_be_u32_rput, ffi_be_u32_rget, ffi_le_i16_rput,
ffi_le_i16_rget, ffi_le_u16_rput, ffi_le_u16_rget,
ffi_le_i32_rput, ffi_le_i32_rget, ffi_le_u32_rput,
ffi_le_u32_rget): New static functions, on big endian.
(ffi_init_types): Wire in these functions for their
corresponding types, on big endian.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The align feature won't work properly on some machines,
since the underlying get and put routines don't handle
misaligned access. We address that here.
* ffi.c (align_sw_get, align_sw_end, align_sw_put_end,
align_sw_put): New macros.
(ffi_i16_put, ffi_i16_get, ffi_u16_put, ffi_u16_get, ffi_i32_put,
ffi_i32_get, ffi_u32_put, ffi_u32_get, ffi_i64_put, ffi_i64_get,
ffi_u64_put, ffi_u64_get, ffi_short_put, ffi_short_get, ffi_ushort_put,
ffi_ushort_get, ffi_int_get, ffi_uint_put, ffi_uint_get, ffi_long_put,
ffi_long_get, ffi_ulong_put, ffi_ulong_get, ffi_float_put,
ffi_float_get, ffi_double_put, ffi_double_get, ffi_val_put, ffi_val_get,
ffi_wchar_put, ffi_wchar_get, ffi_sbit_put, ffi_sbit_get, ffi_ubit_put,
ffi_ubit_get): Insert macros to redirect the transfer to a temporary
aligned buffer if the pointer is misaligned.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (be_uint16_s, be_int16_s, be_uint32_s, be_int32_s,
be_uint64_s, be_int64_s, be_float_s, be_double_s, le_uint16_s,
le_int16_s, le_uint32_s, le_int32_s, le_uint64_s, le_int64_s,
le_float_s, le_double_s): New symbol variables.
(ffi_be_i16_put, ffi_be_i16_get, ffi_be_u16_put,
ffi_be_u16_get, ffi_le_i16_put, ffi_le_i16_get,
ffi_le_u16_put, ffi_le_u16_get, ffi_be_i32_put,
ffi_be_i32_get, ffi_be_u32_put, ffi_be_u32_get,
ffi_le_i32_put, ffi_le_i32_get, ffi_le_u32_put,
ffi_le_u32_get, ffi_be_i64_put, ffi_be_i64_get,
ffi_be_u64_put, ffi_be_u64_get, ffi_le_i64_put,
ffi_le_i64_get, ffi_le_u64_put, ffi_le_u64_get,
ffi_be_float_put, ffi_be_float_get, ffi_le_float_put,
ffi_le_float_get, ffi_be_double_put, ffi_be_double_get,
ffi_le_double_put, ffi_le_double_get): New static functions.
(ffi_init_types): Register new type symbols via typedef
mechanism.
(ffi_init): Initialize new symbol variables.
* ffi.c (be_uint16_s, be_int16_s, be_uint32_s, be_int32_s,
be_uint64_s, be_int64_s, be_float_s, be_double_s, le_uint16_s,
le_int16_s, le_uint32_s, le_int32_s, le_uint64_s, le_int64_s,
le_float_s, le_double_s): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (align_s): New symbol variable.
(struct txr_ffi_type): New function pointer member, clone.
(ffi_simple_clone): New static function.
(make_ffi_type_builtin, make_ffi_type_pointer,
make_ffi_type_enum): Wire in ffi_simple_clone as the clone
function.
(ffi_struct_clone): New static function.
(make_ffi_type_struct): Wire in ffi_struct_clone as the clone
function for struct types.
(ffi_array_clone): New static function.
(make_ffi_type_array): Wire in ffi_array_clone as the clone
function for array types.
(ffi_type_copy): New static function.
(ffi_type_compile): Recognize new (align <num> <type>) syntax.
This works by cloning <type>, and then punching in the
specified alignment. The align syntax then denotes this
modified type.
(ffi_init): Initialize align_s.
* ffi.h (align_s): Declared.
|
|
|
|
|
|
|
| |
* ffi.c (ffi_type_compile): Evaluate width argument
of sbit and ubit type as as expression.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Places where an integer constant was previously allowed
now allow an expression.
The way enum syntax works is now different. A temporary
lexical environment is created, and each enumeration is
bound in that environment. The value expressions are
evaluated in that environment. The decision to allow
keyword symbols to be enumeration contants is retracted.
* eval.h (special_s): Declared.
* ffi.c (ffi_eval_expr): New static function.
(make_ffi_type_enum): Enums are introduced into a temporary
environment, in which the value expressions are evaluated. By
this means, the expressions can refer can refer to previous
enums and do arbitrary computation. Also, we drop the
requirement that enums can be keyword symbols.
(ffi_type_compile): Array dimension and buf size are evaluated
as expresions. Array and buffer syntax is transformed by
substitution of the evaluated size.
* txr.1: Documented use of expressions in FFI type notation.
|
|
|
|
|
| |
* ffi.c (ffi_type_compile): Fix bad indentation brought
about by refactoring.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_alignof, ffi_offsetof, ffi_arraysize,
ffi_elemsize, ffi_elemtype): New functions.
(ffi_init): Registered intrinsics ffi-alignof, ffi-offsetof,
ffi-arraysize, ffi-elemsize, ffi-elemtype.
* ffi.h (ffi_alignof, ffi_offsetof, ffi_arraysize,
ffi_elemsize, ffi_elemtype): Declared.
* lisplib.c (ffi_set_entries): New autoload entries alignof,
offsetof, arraysize, elemsize, elemtype.
* share/txr/stdlib/ffi.tl (alignof, offsetof, arraysize,
elemsize, elemtype): New macros.
* txr.1: Documented new functions and macros.
|
|
|
|
|
| |
* ffi.c (ffi_size): Check for a bitfield type and
diagnose.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (enum_s): New symbol variable.
(struct txr_ffi_type): New member, sym_num, num_sym.
(ffi_enum_type_mark): New static function.
(ffi_type_enum_ops): New static structure.
(ffi_enum_put, ffi_enum_get, ffi_enum_rput, ffi_enum_rget):
New static functions.
(make_ffi_type_enum): New static function.
(ffi_type_compile): Extend with enum syntax.
(ffi_init): Initialize enum_s with new interned symbol.
* ffi.c (enum_s): Declared.
* txr.1: Documented.
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_type_common_mark, ffi_type_mark): New
static function
(ffi_struct_type_mark, ffi_ptr_type_mark): Use new
ffi_type_common_mark function for common members.
(ffi_type_builtin_ops): Wire in ffi_type_mark.
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (pad_retval): Define same way regardless of
big or little endian. For instance, we don't want to
call alloca(1) for a char return value. It could be
the case on little endian targets that libffi prepares
an entire ffi_arg return value. Even though we just read
the low order byte, we still have to prepare enough space
for the whole thing.
|
|
|
|
|
|
|
| |
* ffi.c (ffi_closure_dispatch_safe): In the abort case
when we put zeros in the return value, we must overwrite
the entire ffi_arg cell, in adherence with the special
return value quirk of libffi.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This change gets TXR FFI working on Power PC 64,
big endian. Many thanks to the GCC Compile Farm.
Turns out, the libffi API has changed some years ago,
with outdated documentation lingering. Return values
for the basic integral types must all be handled with
a buffer of type ffi_arg and casting. This is true in
both ffi_call and closures: in both directions.
For instance, if a foreign function returns char, we
must retrieve a ffi_arg value (which might be as
large as 64 bits). Then we must cast this value to
char. In actual fact, on a big endian system with an
8 byte ffi_arg, the char value may be located in byte
7 of the 8 byte buffer, not in byte 0.
FFI's own test suite got this wrong and had to
be patched back in 2013: it was doing things the way
we are doing them:
https://sourceware.org/ml/libffi-discuss/2013/msg00199.html
The doc was updated at the same time to tell the truth:
https://sourceware.org/ml/libffi-discuss/2013/msg00200.html
Luckily, we can fix TXR's ffi module without damaging its
framework. The object model is flexible enough to absorb the
change. Basically, we add two new methods to the txr_ffi_type
objects: virtual functions rget and rput. We only add these
when targetting big endian. These have the same type
signature as get and put, but are specialized for handling
return values. For all integer types smaller than 64 bits,
these functions are separately implemented with distinct
semanics which handle the FFI API requirements with ffi_arg
and casting and all. For all other types, rget and rput
are identical to get and put.
* ffi.c (pad_retval, ifbe, ifbe2): New macros, conditionally
defined for big and little endian.
(struct txr_ffi_type): New members rput and rget.
(ffi_i8_rput, ffi_i8_rget, ffi_u8_rput, ffi_u8_rget,
ffi_i16_rput, ffi_i16_rget, ffi_u16_rput, ffi_u16_rget,
ffi_i32_rput, ffi_i32_rget, ffi_u32_rput, ffi_u32_rget,
ffi_char_rput, ffi_char_rget, ffi_uchar_rput, ffi_uchar_rget,
ffi_bchar_rget, ffi_short_rput, ffi_short_rget,
ffi_ushort_rput, ffi_ushort_rget, ffi_int_rput, ffi_int_rget,
ffi_uint_rput, ffi_uint_rget, ffi_long_rput, ffi_long_rget,
ffi_ulong_rput, ffi_ulong_rget, ffi_wchar_rput): New
functions.
(make_ffi_type_builtin): Take rput and rget arguments,
regardless of platform. On big endian, store these in the
corresponding members. If they are null, duplicate get and put
instead.
(ffi_type_compile, ffi_init_types): Specify the rput and rget
functions for the basic types, using the ifbe macro which
nullifies the references to functions when they don't exist on
little endian. For all other types, pass the new arguments as
null.
(ffi_call_wrap): Pad the return vaue buffer size to a minimum
size on big endian; it must be at least sizeof (ffi_alloc).
Use the rget method for the return value on big endian.
(ffi_closure_dispatch, ffi_closure_dispatch_safe): Use rput on
big endian for storing return value.
|
|
|
|
|
|
| |
* ffi.c (ffi_call_wrap): Don't calculate in_pass_needed
in put loop, since we already calculated it in the argument
buffer allocation loop.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (sbit_s, ubit_s): New symbol variables.
(struct txr_ffi_type): New members, shift and mask.
(ffi_sbit_put, ffi_sbit_get, ffi_ubit_put, ffi_ubit_get,
bitfield_syntax_p): New static functions.
(make_ffi_type_pointer): Disallow pointers to bitfields.
(make_ffi_type_struct): Process bitfield members and
set up shifts and masks accordingly. Recently introduced
bug fixed here at the same time: the alignment calculation
for each member must be done top-of-loop.
(ffi_struct_compile): Exclude bitfields from the check
against members with zero type. Compile the bitfield syntax.
(ffi_typedef): Do not allow typedefs of bitfield type.
Not only doesn't this make sense, but bitfield types
are destructively modified in make_ffi_type_struct: they
are imbued with a mask and offset tied to their position in
a particular struct.
* ffi.h (sbit_s, ubit_s): Delared.
* txr.1: Documented bitfields.
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_type_compile): In the case when a struct type
is compiled and the Lisp struct doesn't exist, the function
creates the struct type. However, the FFI struct type syntax
allows nil as a slot name, indicating a padding field.
These nils must be scrubbed from the slot list when making
the Lisp struct type, or else an error occurs.
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (make_ffi_type_struct): Use calloc for allocating
memb, so all the Lisp objects in it are initially nil. Then
install it into the structure upfront. Afterward, as we
iterate over the slots and types and install them into the
array, we lose references to them. But now since the array is
now wired into the FFI struct type structure, these objects
are now visible to GC.
|
|
|
|
|
|
| |
* ffi.c (ffi_struct_compile): Eliminate redundant call
to ffi_type_compile, replacing it with the compiled type
we already have.
|
|
|
|
|
| |
* ffi.c (ffi_put_into, ffi_in, ffi_get, ffi_out): Add missing
error symbol argument in uw_throwf calls.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This change will make bitfield support easier.
* ffi.c (struct smemb): New member, offs.
(ffi_struct_in, ffi_struct_put, ffi_struct_out,
ffi_struct_get, ffi_struct_release): For each member, refer to
the offset in the memb array, rather than calculating it
on-the-fly.
(make_ffi_type_struct): Calculate the offset for each member.
This is exactly the same as the total_size calculation before;
just the name is changed to offs, and bit operations are used
for the alignment calculations.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (struct smemb): New struct type.
(struct txr_ffi_type): Removed members mnames and mtypes. New
member memb.
(ffi_type_struct_destroy_op): Free the new memb descriptor
array, and overwrite with null pointer.
(ffi_struct_type_mark): Mark eltype only if not nil.
If memb pointer is not nil, walk the array and mark it.
Remove marking of removed mtypes and mnames members.
(ffi_ptr_in_release, ffi_struct_in, ffi_struct_put,
ffi_struct_out, ffi_struct_get, ffi_struct_release): Walk the
struct members using the new array descriptor.
(make_ffi_type_struct): Allocate the memb array, and
initialize it. Remove initialization of mnames and mtypes.
(make_ffi_type_array): Remove initialization of mnames.
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_type_compile): The problem here is using
make_ffi_type_builtin and then installing an eltype. That type
has no gc function that will mark tft->eltype, exposing
the eltype to premature reclamation. We must change these
to use make_ffi_type_pointer. That constructor takes the
element type too, so the code gets simplified.
|
|
|
|
|
|
|
|
|
|
|
|
| |
For pointers, the code still reflects the wrong assumption
that the size and alignment are the same.
* ffi.c (make_ffi_type_pointer): Remove the size argument;
it's always passed as sizeof (mem_t *), which is pointless.
Just initialize the size and align members in a fixed way.
Use sizeof and alignof to do this right.
(ffi_type_compile): Remove size argument from all
make_ffi_type_pointer calls.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (struct txr_ffi_type): New member, eltype. Represents
element type of arrays and target type of pointers, so
that the mtypes member isn't overloaded for this purpose,
and will only represent the list of types of a struct.
(ffi_struct_type_mark): Mark eltype, since this function is
used by arrays also.
(ffi_ptr_type_mark): Mark eltype. Do not mark mtypes,
since the ptr types don't use it any more.
(ffi_varray_alloc, ffi_wchar_get, ffi_cptr_get,
ffi_cptr_alloc, ffi_ptr_in_in, ffi_ptr_in_d_in,
ffi_ptr_in_out, ffi_ptr_out_in, ffi_ptr_out_put,
ffi_ptr_out_out, ffi_ptr_get, ffi_ptr_d_get, ffi_ptr_in_put,
ffi_ptr_out_s_in, ffi_ptr_in_release, ffi_array_in_common,
ffi_array_put_common, ffi_array_out_common,
ffi_array_get_common, ffi_array_release_comon,
ffi_array_null_term_in, ffi_array_null_term_get,
ffi_varray_release, ffi_carray_get, ffi_carray_put): Access
eltype instead of mtypes.
(make_ffi_type_builtin): Don't initialize mnames and mtypes to
nil, since we are using calloc.
(make_ffi_type_pointer): Don't initialize mnames or mtypes to
nil. Do initialize eltype to the target type.
(make_ffi_type_array): Initialize eltype instead of mtypes.
(ffi_type_compile): For cptr and carray, initialize eltype
instead of mtypes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_val_get): Throw an exception if the object
doesn't appear valid.
* gc.c (valid_object_p): New function. Invalid objects are
those that are pointers, but either not into a heap, or else
to a freed object or to an object that is marked by the
garbage collector (should only be seen while GC is running).
All others are valid. There can be false positives here: a
value with the LIT tag is in fact a pointer, but we don't
check whether that is valid.
* gc.c (valid_object_p): Declared.
* txr.1: Remarks added to documentation of FFI val type.
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (val_s): New symbol variable.
(ffi_val_put, ffi_val_get): New functions.
(ffi_init_types): Register val type.
(ffi_init): Initialize val_s.
* ffi.h (val_s): Declared.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Replace the incorrect alignment assumption for the basic types
(size == alignment) with the true calculation obtained from the
compiler.
* ffi.c (alignof): New macro.
(make_ffi_type_builtin): Take alignment as separate argument.
(ffi_type_compile, ffi_init_types): Using alignof macro,
calculate alignment of each type that is created using
make_ffi_type_builtin, and pass to that function.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_call_wrap): Take struct args * parameters
rather than a list. Check that number of arguments
matches required number from call desc. No need
to build argument array any more; we just refer to
the one in args. Also, the first two parameters
are reversed for consistency with other functions.
(ffi_init): Update registration of ffi-call to
reflect type change.
* ffi.h (ffi_call_wrap): Declaration updated.
* txr.1: Documented ffi-call.
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_varray_null_term_in): New static function.
(ffi_type_compile): Wire in new function as in operation
of variable length zarray.
* txr.1: Documented.
|
|
|
|
|
|
|
|
|
| |
* ffi.c (carray_buf_sync): New function.
(ffi_init): carray-buf-sync intrinsic registered.
* ffi.h (carray_buf_sync): Declared.
* txr.1: Documented.
|
|
|
|
|
| |
* ffi.c (carray_buf): Do not allow an element type with
zero size; throw an exception.
|
|
|
|
|
|
|
| |
* ffi.c (carray_buf): Do the buf_get first, then
length_buf, since buf_get takes a self argument.
This way the diagnostic is better if the object
isn't a buf.
|
|
|
|
|
|
|
|
|
| |
* ffi.c (carray_cptr): New function.
(ffi_init): Registered intrinsic.
* ffi.h (carray_cptr): Declared.
* txr.1: Documented.
|
|
|
|
|
|
| |
* ffi.c (ffi_varray_null_term_get): New static function.
(ffi_type_compile): Install the new get function for
variable length zarray.
|
|
|
|
|
|
|
|
|
| |
Ban types like (struct foo (bar void)) or
(array 3 (array int)).
* ffi.c (ffi_struct_compile): Check every element type for
zero size and diagnose.
(ffi_type_compile): Likewise, for arrays.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Continuing on the topic of the previous commit, what if in a
callback an error occurs in the put operation that produces
the return value? In that case we end up clobbering with
the abort_retval or nulling out with zero bytes, either way
potentially leaking memory.
* ffi.c (ffi_closure_dispatch_safe): If the return value type
has release semantics, then as the very first thing, null out
the return value buffer. Then later if a dynamic control
transfer is intercepted, invoke the release semantics before
doing anything to the return value buffer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The problem is that the argument conversions in a FFI call can
bail due to an exception, leaving the argument space partially
initialized, and containing pointers to temporary buffers that
have been allocated with malloc.
In this change, we take care of this problem.
We introduce a new virtual function called release to the FFI
type hieararchy. Most types do not implement this: only types
that have something to free, or aggregates which have to
iterate over element types.
The release virtual relies on pointers being null if nothing
has been allocated. For this reason, we allocate the argument
space and all temporar areas with zero filling.
* ffi.c (zalloca): New macro.
(struct txr_ffi_type): New member function pointer, release.
(ffi_fixed_alloc): Use chk_calloc instead of chk_malloc,
so that any pointers in the area are null.
(ffi_varray_alloc): Use chk_calloc, which simplifies the
code.
(ffi_simple_release, ffi_ptr_in_release, ffi_struct_release):
New static functions.
(ffi_array_release_common, ffi_array_release,
ffi_varray_release): New static functions.
(make_ffi_type_pointer): New argument for specifying release
function.
(make_ffi_type_struct): Initialize release member of type
structure to ffi_struct_release.
(make_ffi_type_array): Initialize release member of type
structure to ffi_array_release.
(ffi_type_compile): Set up release function for varray,
several ptr variants and buf-d.
(ffi_init_types): Set up release function for string types.
(ffi_call_wrap): Internals restructured. Instead of repeatedly
processing type and arg lists, we now store them into arrays
allocated with alloca. We allocate the argument space with
zalloca instead of alloca. Allocating the arguments is
separated from the put conversions into two loops, because
the alloca calls must be outside of the unwind catching
block. This is because the unwind control transfer will roll
back the alloca allocation done since the establishment of
the catch block! A new unwind block now iterates over the
arguments and calls release on each one which has a release
function.
|
|
|
|
|
|
|
| |
* ffi.c (ffi_buf_in): Only get the original pointer if obj
isn't nil; otherwise use a null pointer.
(ffi_buf_d_in): Don't refer to length_buf(obj); obj could
be nil. And anyway, we know the buffer size from the type.
|
|
|
|
|
|
| |
* ffi.c (length_carray): Convert the internal representation
of unknown length, which is a -1 of type cnum, into a nil
return value.
|
|
|
|
|
|
| |
* ffi.c (carray_free): Don't just reset the pointer
to null, but also set the number of elements to zero.
That will prevent indexing operations from dereferencing null.
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* ffi.c (ffi_buf_in): The bug in this one is that if *loc
has been mutated to a null pointer, we want to produce
a nil, rather than to try to duplicate the buffer.
(ffi_buf_d_in): The bug here is that *loc is always
different from origptr, because origptr is from the original
buffer object, whereas we placed a copy of it into *loc.
The semantics is changed. We take ownership of whatever
pointer is there. If it is null, then yield nil.
* txr.1: buf and buf-d documentation revised.
|
|
|
|
|
|
|
|
|
| |
Treat a buffer through a carray view.
* ffi.c (carray_buf): New function.
(ffi_init): Register carray-buf intrinsic.
* ffi.h (carray_buf): Declared.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The idea here is that carrays can have a pointer to some area
that is owned by another object. So that the area doesn't
disappear when the other object becomes garbage, a carray
which does this maintains a pointer to that other object.
* ffi.c (ffi_carray_get): Pass new parameter to make_carray.
(struct carray): New member, ref.
(carray_mark_op): Mark new ref member.
(make_carray): New parameter: the object which is stored in
the structure as ref.
(carray_dup): Null out the ref member. When a carray
is duplicated, it owns its own buffer, and henceforth mustn't
prevent the original object from being reclaimed.
(carray_own): Don't allow a carray to claim ownership
of the pointer if it references another object; we have
no protocol to inform that other object.
* ffi.h (make_carray): Declaration updated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The carray type deals with C array passing conventions
as a pointer to the first element of an array of
unknown size. It fills in the functionality gap not
covered by array and varray.
* ffi.c (carray_s): New symbol variable.
(ffi_carray_get, ffi_carray_put): New static functions.
(ffi_type_compile): Handle (carray <type>) syntax.
(struct carray): New struct type.
(carray_struct, carray_struct_checked, carray_print_op,
carray_mark_op, carray_destroy_op): New static functions.
(carray_borrowed_ops, carray_owned_ops): New static structs.
(make_carray, carray_set_length, carray_dup, carray_own,
carray_free, carray_type, length_carray, carray_get,
carray_vec, carray_blank, vec_carray, list_carray, carray_ref,
carray_refset): New functions.
(ffi_init): Initialize carray_s. Register
carray-set_length, carray_dup, carray_own,
carray-free, carray_type, length_carray,
carray-vec, array_blank, vec_carray, list_carray, carray_ref
and carray-refset intrinsics.
* ffi.h (carray_s): Declared.
(make_carray, carray_set_length, carray_dup, carray_own,
carray_free, carray_type, length_carray, carray_get,
carray_vec, carray_blank, vec_carray, list_carray, carray_ref,
carray_refset): Declared.
|
| |
|