dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) (06/27/86)
This should lay to rest any further arguments about printf(). (linking only with AMIGA.LIB and Astartup.obj, Lattice C 3.03) source executable main() {} 1880 main() {printf("hello\n");} 2376 As you can see, printf() takes 496 bytes, PERIOD, when called from amiga.lib (it may or may not use the DOS run-time library, but that doesn't really matter). -Matt
chapman@pavepaws.berkeley.edu (Brent Chapman) (06/27/86)
In article <8606270438.AA07486@pavepaws> dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) writes: > > This should lay to rest any further arguments about printf(). > > >(linking only with AMIGA.LIB and Astartup.obj, Lattice C 3.03) > >source executable > >main() {} 1880 >main() {printf("hello\n");} 2376 > > As you can see, printf() takes 496 bytes, PERIOD, when called from >amiga.lib (it may or may not use the DOS run-time library, but that doesn't >really matter). > > -Matt What you've just done is pretty useless. You could just as well use puts() for that. printf() is "print FORMATTED". Give us some REAL examples, that actually do some formatting, to see whether or not the code size increases (in other words, whether or not the compiler is smart enough not to include the formatting routines it doesn't need). I'm guessing, but I'd expect code size to increase (I don't have my Amiga yet, so I can't test it myself). Brent -- Brent Chapman chapman@pavepaws.berkeley.edu ucbvax!pavepaws!chapman TANSTAAFL! (There Ain't No Such Thing As A Free Lunch!)
jimm@amiga.UUCP (James D. Mackraz) (06/27/86)
In article <742@ucbcad.BERKELEY.EDU> chapman@pavepaws.UUCP (Brent Chapman) writes: >In article <8606270438.AA07486@pavepaws> dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) writes: >> >>source executable >> >>main() {} 1880 >>main() {printf("hello\n");} 2376 >> > >What you've just done is pretty useless. You could just as well use puts() >for that. printf() is "print FORMATTED". Give us some REAL examples, that >actually do some formatting, to see whether or not the code size increases >(in other words, whether or not the compiler is smart enough not to include >the formatting routines it doesn't need). I'm guessing, but I'd expect >code size to increase (I don't have my Amiga yet, so I can't test it >myself). >Brent Let me be the first in a long line of people commenting on this one. (It's 8:30 am pdt, june 27). It is not the business of the compiler (any compiler?) to interpret the data present at an address passed at run-time to a subroutine, and thereby to determine that certain functions called by that subroutine (in this case, formatters) won't actually actually be needed, and so on to indicate somehow to the linker that those references can be left unresolved. I guess that what I am saying is that you should buy an amiga and program a whole lot and learn a whole lot. jimm Also, I am told that the printf in the kernel (kprintf and the stuff it uses) don't handle floating point. The intent of those routines is for debugging use. I think I am in favor of building printf right into your system, but that wasn't the intent of kprintf, as I understand it. But then again, poof: I may be wrong.
dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) (06/27/86)
>What you've just done is pretty useless. You could just as well use puts() >for that. printf() is "print FORMATTED". Give us some REAL examples, that >actually do some formatting, to see whether or not the code size increases >(in other words, whether or not the compiler is smart enough not to include >the formatting routines it doesn't need). I'm guessing, but I'd expect >code size to increase (I don't have my Amiga yet, so I can't test it >myself). >Brent Dummy, how does the linker know you aren't printf()'ing any formatted stuff? it doesn't... it has to include the code anyway. Thus: main(){printf("%ld %8lx\n", 20, 30);} code size = 2392 up 16 bytes from 2376 (the extra text) satisfied? -Matt
rico@oscvax.UUCP (06/29/86)
In article <8606270438.AA07486@pavepaws> dillon@PAVEPAWS.BERKELEY.EDU.UUCP writes: > > This should lay to rest any further arguments about printf(). > > >(linking only with AMIGA.LIB and Astartup.obj, Lattice C 3.03) > >source executable > >main() {} 1880 >main() {printf("hello\n");} 2376 > > As you can see, printf() takes 496 bytes, PERIOD, when called from >amiga.lib (it may or may not use the DOS run-time library, but that doesn't >really matter). > > -Matt Just for comparison, I thought it would be interesting to list figures for Aztec C. These numbers are with the standard 16 and 32 bit libraries, there is no distinction between 'amiga.lib' and 'lc.lib' or whatever as is found in Lattice (also no startup code to link in....) source executable main() {} 1580 16 bit ints 1636 32 bit ints main() {printf("hello\n");} 4712 16 bit ints 4944 32 bit ints Another FYI .... on Fish disk #23, there are four versions of microemacs V30, two of the were compiled with Lattice and two with Manx... presumably, the same source was used for both file executable xemacs.amigados.lattice 68356 xemacs.amigados.manx16 39928 gemacs.intuition.lattice 80312 gemacs.intuition.manx16 46976 and on fish disk #24, we find Matt Dillon's csh-ish shell (thanks Matt!!) csh.lattice 38052 csh.manx32 21180 Lattice seems to have blown more than just their run time library (I say that a lot don't I :-) ) -Rico
fnf@unisoft.UUCP (Fred Fish) (06/30/86)
Ok folks, one thing nobody seems to have mentioned yet in these Manx vs Lattice file size comparisons is the effect of object file overhead (symbol table, hunk headers, etc). Only after someone writes the equivalent of the Unix "size" command, can we begin to do any meaningful size comparisons. -Fred
mykes@3comvax.UUCP (Mike Schwartz) (07/01/86)
In article <8606270438.AA07486@pavepaws> dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) writes: > > This should lay to rest any further arguments about printf(). > > >(linking only with AMIGA.LIB and Astartup.obj, Lattice C 3.03) > >source executable > >main() {} 1880 >main() {printf("hello\n");} 2376 > > As you can see, printf() takes 496 bytes, PERIOD, when called from >amiga.lib (it may or may not use the DOS run-time library, but that doesn't >really matter). > > -Matt Is there any chance that Amiga.lib's printf() calls a printf() that is in rom somewhere (like in ROMWack???)? It does not make sense that even a simple printf() would be so small.
mykes@3comvax.UUCP (Mike Schwartz) (07/01/86)
In article <84@unisoft.UUCP> fnf@unisoft.UUCP (Fred Fish) writes: >Ok folks, one thing nobody seems to have mentioned yet in these >Manx vs Lattice file size comparisons is the effect of object file >overhead (symbol table, hunk headers, etc). Only after someone >writes the equivalent of the Unix "size" command, can we begin >to do any meaningful size comparisons. > >-Fred A friend of mine is porting a Mac game to the Amiga (Deja Vu - a.k.a. Amiga Vu). I brought my compiler over to his house the other day and compiled his program. The executable went from 55K down to 32K, without any editting (i.e. removal of code). As much as I do not like the Lattice implementation, I find it hard to believe that this 23K reduction was due to library calls alone, but I also find it hard to believe that Lattice does not generate reasonable code. Manx, using the +l option, is not a very good code generating compiler - it just buries Lattice in terms of compiling speed, program size (the size of the compiler, linker and assember is the size of LC1 alone). But I cringe when I look at the code generated, I am amazed at how poor it is. For example, the following statement: if (var == NULL) ... causes var to be first loaded, extended to a word, extended to a long, then compared against 0, EVEN when var is declared as a UBYTE... Oh, well... I guess someone will make a good 'C' compiler someday...
ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) (07/03/86)
[ Sorry, but the line eating bug is on a diet. ] In article <562@3comvax.UUCP> mykes@3comvax.UUCP (Mike Schwartz) writes: >In article <8606270438.AA07486@pavepaws> dillon@PAVEPAWS.BERKELEY.EDU (Matt Dillon) writes: >> This should lay to rest any further arguments about printf(). >>(linking only with AMIGA.LIB and Astartup.obj, Lattice C 3.03) >> >>source executable >>main() {} 1880 >>main() {printf("hello\n");} 2376 >> >> As you can see, printf() takes 496 bytes, PERIOD, when called from >>amiga.lib (it may or may not use the DOS run-time library, but that doesn't >>really matter). >> -Matt >Is there any chance that Amiga.lib's printf() calls a printf() that is in >rom somewhere (like in ROMWack???)? It does not make sense that even a >simple printf() would be so small. Part of Kiskstart is, in fact, the debugging library. The routines documented in debug.lib are: KDoFmt: Format data into character stream KGetChar: Get a character from the debug console (9600 baud terminal) KMayGetChar: Return char from debug console iff present (doesn't block) KPutChar: Send character to debug console KPutFmt: Print formatted data to debug console KPutStr: Put a string to debug console I'm sure they figured out a way to fool these routines into doing the formatting without sending data to the debug console (KDoFmt is probably the key). Note: This is all educated guessing, so I'm obviously wrong. For more complete information on the debugging library, check the pages just before Appendix G in the RKM, vol 2. -------- On a completely different tack: What is the Clist library for? Yes, I know what it does (the auto docs explain that), but what's it *for*? I'm having trouble discovering a use for it. Is it for manipulating a list of strings, or what? [[ the Clist.lib autodocs start at page A-47, RKM, vol 2 ]] _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ Leo L. Schwab ihnp4!ptsfa!well!ewhac ..or.. "Work FOR? I don't work FOR well ---\ anybody! I'm just having fun." dual ----> !unicom!ewhac hplabs -/ ("AE-wack")
ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) (07/03/86)
[ Go ahead. Eat me. See if I care. ] In article <566@3comvax.UUCP> mykes@3comvax.UUCP (Mike Schwartz) writes: >Manx, using the +l option, is not a very good code generating compiler - >it just buries Lattice in terms of compiling speed, program size (the >size of the compiler, linker and assember is the size of LC1 alone). But >I cringe when I look at the code generated, I am amazed at how poor it is. >For example, the following statement: > if (var == NULL) ... >causes var to be first loaded, extended to a word, extended to a long, then >compared against 0, EVEN when var is declared as a UBYTE... > >Oh, well... I guess someone will make a good 'C' compiler someday... It never fails to amaze me just how many people do this: if (foo == NULL) { ... } or: if (foo == 0) { ... } The reason the compiler is exhibiting the behavior you describe is because you told it to. You are asking the compiler to compare an unsigned byte to the literal value of NULL. If you look in exec/types.h, you'll find NULL defined this way: #define NULL 0L So you're asking the compiler to compare a byte to a long. So it expands the byte to a long, then makes the comparison using a CMP instruction. That *IS* what you told it to do. What I can't understand is why more people don't do this: if (!foo) { ... } This will do what you want, which is TST the byte to see if it's non-zero. If you *really* care about optimized code, compile to an assembly source file and bang on it yourself. That's something Lettuce *definitely* won't let you do. --------I N T E R L U D E-------- I really hate this damn compiler. I wish that they would sell it. It never does just what I want, But only what I tell it. -------- Think about it (not too much; it's intended to be humorous). _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ Leo L. Schwab ihnp4!ptsfa!well!ewhac ..or.. "Work FOR? I don't work FOR well ---\ anybody! I'm just having fun." dual ----> !unicom!ewhac hplabs -/ ("AE-wack")
mwm@eris.berkeley.edu (07/08/86)
In article <1385@well.UUCP> ewhac@well.UUCP (Leo 'Bols Ewhac' Schwab) writes: > It never fails to amaze me just how many people do this: > if (foo == NULL) { ... } > or: > if (foo == 0) { ... } [instead of...] > if (!foo) { ... } Well, I wrote it the way you think people ought to for 8 years before changing to coding the test explicitly. I changed because the (!foo) notation is less readable than the (foo == 0) notation. Also, if foo is a pointer type, the test (!foo) is wrong. NULL doesn't have to be zero. > The reason the compiler is exhibiting the behavior you describe is >because you told it to. You are asking the compiler to compare an unsigned >byte to the literal value of NULL. Uh, what he got was: >>causes var to be first loaded, extended to a word, extended to a long, then >>compared against 0, EVEN when var is declared as a UBYTE... What's the second extend doing in there? Anything claiming to be a reasonable compiler should generate ONE extend. Anything claiming to be not bad (much less good) should realize what's going on, and generate the CMP.B instruction. Of course, a good compiler will check to see if the Z condition code is set correctly already (from a move to/from var, or the evaluation into var), and just generate the branch. If it's slightly intelligent, it'll be willing to re-arrange code to make that pre-condition happen. > If you *really* care about optimized code, compile to an assembly >source file and bang on it yourself. That's something Lettuce *definitely* >won't let you do. Well, I'd rather get the source to the compiler and bang on that so it generates good code (that way I only have to do it once). But I expect the compiler to at least generate non-abysmal code. >>Oh, well... I guess someone will make a good 'C' compiler someday... DEC has one for VMS. Convex has one for their box (though it may not be released yet). Anybody know of any others? <mike
guy@sun.uucp (Guy Harris) (07/09/86)
> > It never fails to amaze me just how many people do this: > > if (foo == NULL) { ... } > > or: > > if (foo == 0) { ... } > [instead of...] > > if (!foo) { ... } > > Well, I wrote it the way you think people ought to for 8 years before > changing to coding the test explicitly. I changed because the (!foo) > notation is less readable than the (foo == 0) notation. Amen. The three constructs given have exactly the same meaning in C (yes, wait for the explanation, it's true) and any good compiler will produce exactly the same code for them. However, "!foo" is suggestive of testing for the falsity of a Boolean (yes, I know C doesn't have a formal Boolean type, but that's the proper way to think of something with values meaning "true" and "false"), while "foo == NULL" is suggestive of testing whether a pointer is null or not, and "foo == 0" is suggestive of testing whether an integral value is zero or not. > Also, if foo is a pointer type, the test (!foo) is wrong. NULL doesn't > have to be zero. Oh, yes it does. A null pointer need not have a bit pattern consisting of all zeroes. However, the value of a null pointer is constructed in C by converting the integral constant 0 to a pointer type. In the construct "foo == 0", the LHS is a pointer, so the compiler knows enough to convert the "0" on the RHS to a pointer of the same type, hence a null pointer of the appropriate type. (No, I won't cite the K&R/ANSI C draft which says this; seek and ye shall find.) As such, NULL should be #defined as 0 - NOT "(char *)0", because that causes the compiler to get annoyed when you compare an "int *" against NULL, since you're comparing two different kinds of pointers. > > The reason the compiler is exhibiting the behavior you describe is > >because you told it to. You are asking the compiler to compare an unsigned > >byte to the literal value of NULL. Which should always be 0. As such, in the example given, if (var == NULL) ... is identical to if (var == 0) ... and should generate the same code; as the author of the response to the above comment points out, there is NO reason to extend a 1-byte variable "var" to 4 bytes when doing this. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com (or guy@sun.arpa)
pete@valid.UUCP (Pete Zakel) (07/10/86)
> >>causes var to be first loaded, extended to a word, extended to a long, then > >>compared against 0, EVEN when var is declared as a UBYTE... > > What's the second extend doing in there? Anything claiming to be a > reasonable compiler should generate ONE extend. Not if the processer is a 68000 or 68010. There is NO instruction to extend byte to long. Fortunately that was fixed in the 68020, but that doesn't help unless you have a compiler that understands 68020 AND you know all your target machines have 68020s. -- -Pete Zakel (..!{hplabs,amd,pyramid,ihnp4}!pesnta!valid!pete)
mykes@3comvax.UUCP (07/11/86)
In article <4907@sun.uucp> guy@sun.uucp (Guy Harris) writes: > >Which should always be 0. As such, in the example given, > > if (var == NULL) ... > >is identical to > > if (var == 0) ... > >and should generate the same code; as the author of the response to the >above comment points out, there is NO reason to extend a 1-byte variable >"var" to 4 bytes when doing this. >-- > Guy Harris > {ihnp4, decvax, seismo, decwrl, ...}!sun!guy > guy@sun.com (or guy@sun.arpa) As author of the original article, I would just like to point out that the NULL in he case I described was NOT 0L (I removed all the Ls form the include files - i use +l all the time so I dont need them). I had hoped that removing the Ls, this would make the "problem" go away but no luck. Simple peephole optimization hould catch most of the stuff I see wrong wit MANX. I also acknowledge that the +l option was an "afterthought", having been added maybe days before 3.20A shipped. I still would rather stick with their product for the next few years, because they do have the better compiler, a head start on everyone else (at making a good Amiga library), excellent support and a bright future. I will probably pay for updates forever... This discussion has brought out a few interesting points: if you consider the compiler a tool to generate the program you want (which I do), then you have to play some tricks and use a style that makes the compiler generate better code. On one hand, future compilers (versions of compilers) may not generate optimal code for this style, but what you get today is closest to the binary program that you want (i.e. fast, compact, etc.) as doable with the current version of the compiler. On the other hand, if you code for portability, there are less of these tricks (there probably are a few though) that work across all compilers and all machines. Matt Dillon's comments about longs and shorts and ints are valid and his approach is valid, when you consider his intentions (purism aside). For now, I do use: if (!pointer) ... instead of if (pointer == NULL) ... because no matter how much RAM I have, I seem to always want more. Coding this way saves me RAM all the time.