[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bit fields in defstruct
Date: 15 Apr 86 00:17 EST
From: Dave.Touretzky@A.CS.CMU.EDU
Can someone tell me why Common Lisp defstruct doesn't support bit fields?
This is a Zetalisp feature that I make heavy use of. The equivalent feature
in Common Lisp would look something like:
(defstruct thingie
(foo 'default-foo-value)
((low-bar (byte 8 0))
(mid-bar (byte 8 8) #x00 :read-only t) ;filled by constructor
(high-bar (byte 8 12) #x1a))
(baz 'default-baz-value))
This makes THINGIE a vector with 4 elements (counting the structure name);
the second element is an integer with default value #x1a0000. The structure
has 5 access functions:
THINGIE-FOO
THINGIE-LOW-BAR
THINGIE-MID-BAR
THINGIE-HIGH-BAR
THINGIE-BAZ
The access function for -BAR slots expands to a LDB, and the SETF macro
expands to a DPB. The knowledge that three of the slots of a THINGIE are
bit fields of the same integer is hidden from the rest of the program.
The reason I need this feature is I am building thousands of instances of a
particular structure, and the difference between representing half a dozen
bit fields with one integer versus six integers is significant in terms of
memory cost. I don't think a user should build his own access functions for
bit fields; I think defstruct should do that for him.
Two things:
(1) Syntax. What do you think about
(defstruct thingie
(foo 'default-foo-value)
((low-bar 0 :byte-field (byte 8 0))
(mid-bar #x00 :byte-field (byte 8 8) :read-only t)
(high-bar #x1A :byte-field (byte 8 12)))
(baz 'default-baz-value))
instead of yours? Yes, I know the default value must be specified, but
this syntax is consistent with non-nested syntax. I propose that a
value of NIL means that it isn't filled in (and isn't forced to zero
(see [3]).
(2) Performance. Users should be wary that doing such things has
efficiency issues depending on the boundaries between fixnum and bignum.
That is, since the fields are integers, a user could accidentally go
consing a lot of bignums, where a normal defstruct wouldn't.
[3, In your example, mid-bar and high-bar overlap. mid-bar gets filled
in by the constructor, and high-bar has a default. How are these
merged, since they overlap?]
PS: I suppose if defstruct were highly optimizing one could declare six
fields of :TYPE BIT and expect them to be packed into one word. This
doesn't solve everything though; in some cases (like when communicating
with external programs) one wants to specify the exact postion of each bit
field in a word. Also, one might want to have overlapping bit fields in the
same word, such as three 1-bit fields and a 3-bit field that covers them.
Indeed, this is one of the motivations for Symbolics extending defstruct
along these lines. Normal users don't need this; it is usually used for
interfacing to hardware device registers, and sometimes network packets
that have overlapping fields themselves.