devine@cookie.dec.com (Bob Devine) (01/08/88)
Path: decwrl!labrea!rutgers!cmcl2!brl-adm!brl-smoke!gwyn Subject: Re: what C needs I wrote: >When writing code that requires control of alignment or location, > [...I want a way to pack a structure] Doug Gwyn wrote: > If you're under the impression that a simple, efficient mechanism > exists or could feasibly be made to exist for "rolling in" raw binary > data obtained from another system, you're sadly mistaken. No, I didn't want a full-blown XDR or presentation layer type of function. What I described was smaller. I stemmed from an experience where two vendor's compilers where used on the same architecture but with different layouts of data. Frustrating! A different argument for providing packed/unpacked structures is simply to allow the programmer to choose between access speed or smaller data segment. As an example of prior art, Microsoft C has a compile time flag for this. Granted, not all structures would be packed the same way or even could be packed. Some architectures allow ints to be only integer aligned (pyramid, I believe) while others all ints to be char aligned (vax). Consider this suggestion in light of the C philosophy or letting the programmer decide.
nevin1@ihlpf.ATT.COM (00704A-Liber) (01/09/88)
In article <8801071842.AA04669@decwrl.dec.com> devine@cookie.dec.com (Bob Devine) writes:
.Path: decwrl!labrea!rutgers!cmcl2!brl-adm!brl-smoke!gwyn
.Subject: Re: what C needs
.
.I wrote:
..When writing code that requires control of alignment or location,
.. [...I want a way to pack a structure]
.
. A different argument for providing packed/unpacked structures is
.simply to allow the programmer to choose between access speed or
.smaller data segment. As an example of prior art, Microsoft C has
.a compile time flag for this. Granted, not all structures would
.be packed the same way or even could be packed. Some architectures
.allow ints to be only integer aligned (pyramid, I believe) while
.others all ints to be char aligned (vax).
.
. Consider this suggestion in light of the C philosophy or letting
.the programmer decide.
I do not believe that this should be implemented as a feature of the language;
This is best left to defining library routines for packing/unpacking data.
--
_ __ NEVIN J. LIBER ..!ihnp4!ihlpf!nevin1 (312) 510-6194
' ) ) "The secret compartment of my ring I fill
/ / _ , __o ____ with an Underdog super-energy pill."
/ (_</_\/ <__/ / <_ These are solely MY opinions, not AT&T's, blah blah blah
dag@chinet.UUCP (Daniel A. Glasser) (01/09/88)
In article <8801071842.AA04669@decwrl.dec.com> devine@cookie.dec.com (Bob Devine) writes: [lots of junk deleted] > A different argument for providing packed/unpacked structures is >simply to allow the programmer to choose between access speed or >smaller data segment. As an example of prior art, Microsoft C has >a compile time flag for this. Granted, not all structures would >be packed the same way or even could be packed. Some architectures >allow ints to be only integer aligned (pyramid, I believe) while >others all ints to be char aligned (vax). > > Consider this suggestion in light of the C philosophy or letting >the programmer decide. This is not so easy. Yes, the VAX, 8088, and many other processors allow access of data at any byte alignment, but many don't. If you have a packed type on a PDP-11 or 68000 you must use several instructions to fetch a word or long or other multi-byte type any time you access any structure through a pointer. Take the following bit of C code: struct yerks { char y_foo; int *y_fie; char y_poo; }; struct yerks *w; int i; i = *w->y_fie; The assignment, on a PDP-11, takes code to the effect of the following: mov _w, r0 clr -(sp) movb 1(r0), (sp) movb 2(r0), 1(sp) mov @(sp)+, _i Now, assume that you are on a 68000 -- movea.l _w, a0 moveq $0, d0 move.l d0, -(sp) move.b 1(a0), (sp) move.b 2(a0), 1(sp) move.b 3(a0), 2(sp) move.b 4(a0), 3(sp) movea.l (sp)+, a0 move.w (a0), _i; Okay, that not seem too painful? No, packed structures do not belong in the standard. A particular compiler can pack structures as an option, or by default, but that is not going to be portable. Period. C is supposed to be an efficient language. If you really need packed structures, and want them portable, code them directly with macros and unions. -- Daniel A. Glasser ...!ihnp4!chinet!dag ...!ihnp4!mwc!dag ...!ihnp4!mwc!gorgon!dag One of those things that goes "BUMP!!! (ouch!)" in the night.
ok@quintus.UUCP (Richard A. O'Keefe) (01/11/88)
In article <2083@chinet.UUCP>, dag@chinet.UUCP (Daniel A. Glasser) writes: > struct yerks { char y_foo; int *y_fie; char y_poo; }; > struct yerks *w; > int i; > i = *w->y_fie; He claims that this assignment would turn into 9 M680x0 instructions. Wrong. It can be coded in three: movl _w, a0 movl 1(a0), a0 movl (a0), _i The /370, and the 80386 can also handle misaligned data. The R2000 can handle misaligned data at the cost of one extra instruction *if* the compiler knows the data are misaligned, which in this case it would. None of this spoils Glasser's real point, namely that packing is machine-dependent, and doesn't come free on any machine. Even the machines that will handle his example in few instructions tend to take lots more *cycles* to handle misaligned data. (A loop like register int n = {something}; register long *d = {something}; register long *s = {something}; while (--n >= 0) *d++ = *s++; takes about 30% longer for misaligned than for aligned data on a 68020.) Glasser says > No, packed structures do not belong in the standard. He's absolutely right. We already *have* bitfields, after all.
gnu@hoptoad.uucp (John Gilmore) (01/11/88)
dag@chinet.UUCP (Daniel A. Glasser) wrote: > Take the following bit of C code: > struct yerks { > char y_foo; > int *y_fie; > char y_poo; > }; > struct yerks *w; > int i; > i = *w->y_fie; > The assignment, on a PDP-11, takes code to the effect of the following: > [five instructions] > Now, assume that you are on a 68000 -- > [nine instructions -- not optimal either] > Okay, that not seem too painful? > No, packed structures do not belong in the standard... > C is supposed to be an efficient > language. If you really need packed structures, and want them portable, > code them directly with macros and unions. To me this looks like an argument *for* packed structures. Is the author proposing that if we want to access data defined by an outside constraint, we should write assembly language routines? I would rather have the C compiler figure out the difference between the PDP-11 assembler sequence and the 68000 sequence, thank you. Or how is he proposing that we write "portable" definitions using macros and unions, which are just as dependent as structs on compiler alignment, word size, etc? What ends up happening is that a C struct is defined which works on the current compiler; this gradually gets hacked with #ifdef's to work on various compilers as needed, but it still has to depend on individual compilers' ideas of alignment constraints, since the C language allows the compiler to add padding between members or bitfields with impunity. I had to write and maintain a lot of code like this which accessed device registers on the Sun CPU board, or control block layouts in memory that were shared with Ethernet chips or disk controllers or whatever. It was all heavily compiler dependent and I'm sure it broke when ported to the Sun-4, but we didn't have any better tools in C for this. What we need is a portable way to tell the compiler, "don't add any padding -- just lay down the bits like I tell you." You could precede a structure declaration with "#pragma packed", which would require the structure definition to declare all its fields as bitfields (not allowing the element sizes to default) and to declare each field either signed or unsigned (not allowing the signedness to default). The resulting structure would contain exactly those bitfields, laid down end-to-end in big-endian order, without regard to any alignment considerations. This would still not resolve floating point formats, or ones' complement versus twos' complement signed integers, but the rest of the "binary data description problem" (including the #ifdef BIG_ENDIAN / LITTLE_ENDIAN hassle) would be solved. This is too unformed an idea for this C standard, but if some people implement it, like it, and it doesn't have hidden problems, maybe for the next one. -- {pyramid,ptsfa,amdahl,sun,ihnp4}!hoptoad!gnu gnu@toad.com I forsee a day when there are two kinds of C compilers: standard ones and useful ones ... just like Pascal and Fortran. Are we making progress yet? -- ASC:GUTHERY%slb-test.csnet
dag@chinet.UUCP (Daniel A. Glasser) (01/12/88)
In article <3816@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes: [Excerpts from an article I posted deleted] > >To me this looks like an argument *for* packed structures. Is the >author proposing that if we want to access data defined by an outside >constraint, we should write assembly language routines? I would >rather have the C compiler figure out the difference between the PDP-11 >assembler sequence and the 68000 sequence, thank you. Or how is he >proposing that we write "portable" definitions using macros and unions, >which are just as dependent as structs on compiler alignment, word size, >etc? Well, no, this was in oposition to packed structures being mandated by the standard. Different machine archetectures support different packing schemes. The requirements placed on the compiler code generation when packed structures are being used may be easy on one machine and very hard on another. I am willing to be convinced otherwise, but I would need to see a 68000 (not 68020) compiler that supports packed structures before I would be ready to rewrite the compilers that I work on to support these things. I do have a few questions for those who want packed structures: 1) must the packed "keyword" be in the structure definition or just with the declaration? ie: packed struct rowdy { char r_y; int r_i; struct rowdy *r_next; }; struct rowdy wow; vs. struct rowdy { char r_y; int r_i; struct rowdy *r_next; }; packed struct rowdy wow; struct rowdy why; The second is more 'C' like, but really screws up what r_i and r_next might mean in a given context, let alone what happens if you say "why = wow". 2) There is this "prior-art" thing. Yes, some compilers give you switches to select which way you want structures packed, but this is not a semantic change to the language, and god have mercy on the soul of the programmer who mixes modules compiled with different packing strategies. Yes, Pascal also provides packed types; C is not Pascal. Have you ever encountered a C compiler for an archetecture that does impose alignment restrictions on multi-byte simple types (not just a performance penalty, ala 808[86]) that provides packed structures? I have not, and I've seen lots of compilers. If you want to have packed structures in C, find a vendor who is willing to provide them or write an implementation yourself, make sure the extension is clean and does not violate too many C conventions and see that the rest of the world gets to see this extension and it becomes popular. Then participate in the continuing ANSI C committee and see that this extension makes it into the next standard. ANSI does not disallow a compiler from providing extensions. Extensions are just not portable, and should be disableable. -- Daniel A. Glasser ...!ihnp4!chinet!dag ...!ihnp4!mwc!dag ...!ihnp4!mwc!gorgon!dag One of those things that goes "BUMP!!! (ouch!)" in the night.
dag@chinet.UUCP (Daniel A. Glasser) (01/13/88)
In article <519@cresswell.quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: +In article <2083@chinet.UUCP>, dag@chinet.UUCP (Daniel A. Glasser) writes: ++ struct yerks { char y_foo; int *y_fie; char y_poo; }; ++ struct yerks *w; ++ int i; ++ i = *w->y_fie; +He claims that this assignment would turn into 9 M680x0 instructions. +Wrong. It can be coded in three: + movl _w, a0 + movl 1(a0), a0 + movl (a0), _i [rest of article omitted] I specified M68000. I know that the 68020 relaxes this restriction. I also think that the T-11 (lsi-11 on a single 8085 style chip) relaxes this restriction. There are still lots of 68000 and 68010 chips in use out here. Richard's example causes an address error on the M68000. -- Daniel A. Glasser ...!ihnp4!chinet!dag ...!ihnp4!mwc!dag ...!ihnp4!mwc!gorgon!dag One of those things that goes "BUMP!!! (ouch!)" in the night.
woods@tslanpar.UUCP (Greg A. Woods ) (01/26/88)
I'm sorry, but a compile time flag is far from what could solve problems with imposing structure on external data. Just how do you expect to compile a module that must load data into a packed structure on one line, and then perform an ioctl() call on the next to work? (Most kernel's and device drivers won't use packed structures!) How are you to prevent an unknowing programmer from doing such a thing? The "-pack" option of the Microsoft family of C compilers (yes it's still there in Xenix) was a quick and dirty fix for Lattice's mistake of packing structures in the first place (it wastes a lot of CPU time in may implementations). The only possible solution could be the pseudo-functions: pack() and unpack() ala Pascal. I personally have had no problems with bit/byte wise manipulation of external data (using bitfields and unsigned character arrays). -- Greg Woods. UUCP: utgpu!woods, utgpu!{ontmoh, tmsoft!tslanpar}!woods, woods@tslanpar VOICE: (416) 242-7572 LOCATION: Toronto, Ontario, Canada