diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-05-25 20:31:36 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-05-25 20:31:36 -0700 |
commit | a16a267958fb76b5cb1d7154d7c11800b6daeae5 (patch) | |
tree | ca97ab15ca420067bf5f040df06da9096623fb27 /txr.1 | |
parent | 5c676f789d9e896f4b8d88a977d4e0fcae3a9fc1 (diff) | |
download | txr-a16a267958fb76b5cb1d7154d7c11800b6daeae5.tar.gz txr-a16a267958fb76b5cb1d7154d7c11800b6daeae5.tar.bz2 txr-a16a267958fb76b5cb1d7154d7c11800b6daeae5.zip |
ffi: bitfield support.
* 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.
Diffstat (limited to 'txr.1')
-rw-r--r-- | txr.1 | 129 |
1 files changed, 129 insertions, 0 deletions
@@ -53770,6 +53770,11 @@ anonymous padding member simply generates a skip of the number of byte corresponding to the size of its type, plus any necessary additional padding for the alignment of the subsequent member. +Structure members may be bitfields, which are described using the +.code ubit +and +.code sbit +compound type operators. .meIP (array < dim << type ) The FFI .code array @@ -54114,6 +54119,130 @@ object. The get semantics retrieves a Lisp value without freeing. +.meIP ({ubit | sbit} << width ) +The +.code ubit +and +.code sbit +types denote C language style bitfields. These types can only appear +as members of structures. A bitfield type cannot be the argument or return +value of a foreign function or closure, and cannot be a foreign variable. +Arrays of bitfields and pointers, of any kind, to bitfields are a forbidden +type combination that is rejected by the type system. + +The +.code ubit +type denotes a bitfield of type +.codn uint , +corresponding to an +.code unsigned +bitfield in the C language. + +The +.code sbit +type denotes a bitfield of type +.codn int . +Unlike in the C language, it is not implementation-defined whether such +a bit-field represents signed values; it converts between Lisp integers +that may be positive or negative, and a foreign representation which is +two's complement. + +Bitfields of any other type are not supported. + +The +.meta width +parameter of the type indicates the number of bits. It may range from +zero to the number of bits in the +.code uint +type. + +In a structure, bitfields are allocated out in storage units which have the +same width and alignment requirements as a +.codn uint . +These storage units themselves can be regarded as anonymous members of the +structure. When a new unit needs to be allocated in a structure to hold +bitfields, it is allocated in the same manner as a named member of type +.code uint +would be at the same position. + +If a bitfield with non-zero width is not preceded by any non-zero-width +bitfield, then a new unit is allocated, and the bitfield is placed into the +first available position in that unit. On a big-endian machine, the first +available position starts at the most significant bit of the underlying +storage word. On a little-endian machine, the first available bit position +is the least significant bit of the storage word. + +If a non-zero-width bitfield is preceded by a non-zero-width bitfield, then +the new bitfield is packed into the same storage unit as that bitfield if +there is enough remaining room in that unit. Otherwise, it is placed into a +new unit. Bitfields are not split across unit boundaries. + +A zero-length bitfield is permitted. It may be given a name, but the field +will not perform any conversions to and from the corresponding slot in the +Lisp structure. Note that the FFI struct definition itself causes the +corresponding Lisp structure type to come into existence, then the Lisp +structure type will have slots for all the zero width named bitfields, +even though those slots don't participate in any conversions in conjunction +with the FFI type. + +A zero-length bitfield functions in a similar manner in the FFI type +system as in the C language. If it is placed between two bitfields, then it +forces them to be in separate storage units. That is to say, the bitfield +which follows is placed into a new storage unit, even if the previous +bitfield leaves enough room in it storage unit. + +A zero-length bitfield that does not appear between non-zero-length +bitfields has no effect. + +A +.code ubit +field stores values which follow a pure binary enumeration. For instance, +a bit field of width 4 stores values from 0 to 15. On conversion from +the Lisp structure to the foreign structure, the corresponding member +must be a integer value in this range, or an error exception is thrown. + +On conversion from the foreign representation to Lisp, the integer +corresponding to the bit pattern is recovered. Bitfields follow the +bit order of the underlying storage word. That is to say, the most +significant binary digit of the bitfield is the one which is closest +to the the most significant bit of the underlying storage unit. +If a four-bit field is placed into an empty storage unit and the value +8 its stored, then on a big-endian machine, this has the effect of +setting to 1 the most significant bit of the underlying storage word. +On a little-endian machine, it has the effect of setting bit 3 of +the word (where bit 0 is the least significant bit). + +The +.code sbit +field creates a correspondence between a range of Lisp integers, +and a foreign representation based on the two's complement system. +The most significant bit of the bit field functions as a sign bit. +Values whose most significant bit is clear are positive, and use +a pure binary representation just like their +.code ubit +counterparts. The representation of negative values is defined +by the "two's complement" operation, which maps each value to +its additive inverse. The operation consists of temporarily treating the +entire bitfield as unsigned, and inverting the logical value of all the +bits, and then adding 1 with "wrap-around" to zero if 1 is added to a field +consisting of all 1 bits. (Thus zero maps to zero, as expected). +An anomaly in the two's complement system is that the most negative +value has no positive counterpart. The two's complement operation +on the most negative value produces that same value itself. + +A +.code sbit +field of width 1 +can only store two values: -1 and 0, represented by the bit patterns +1 and 0. An attempt to convert any other integer value to a +.code sbit +field of width 1 results in an error. + +A +.code sbit +field of width 2 can represent the values -2, -1, 0 and 1, which are +stored as the bit patterns 10, 11, 00 and 01, respectively. + .meIP ({buf | buf-d} << size ) The parametrized .code buf |