nz@hotlg.UUCP (09/29/87)
One of the developers came upon a very interesting problem with our C cross-compiler the other day. The compiler runs on a VAX (SysV.2) and produces code for the M68000/10. He was write a few modules, one of which contained a label and a few goto statements. When he finished writing the code, he went to try to build a complete product including his new code (a complete load, as we call it). Well, it bombed with a message about the symbol ``cleanup'' being undefined. That symbol was his goto label -- and it appeared right there in the file. The structure of the code was something like this: #include "hugefile.h" foo * dosomefoo(x,y,z) int x,y,z; { int a,b,c; printf("a message"); { short s1, s2; char *cp; if (diagnose(x) < 0) { printf("x failed"); goto cleanup; } if (diagnose(y) < 0) { printf("y failed"); goto cleanup; } diagnose(z); } cleanup: a = x * y; dosomebar(a); return(NULL); } What is the problem here, you ask? Why was it that I, the compiler support person, could not duplicate the problem when I tried to write some little test programs. Why was it that whenever the number of declarations in the dozens of #included header files was changed, the problem would go away? Why was it that other files with similar structure did not evoke the fatal-error behaviour? Can amybody guess? Don't hit the space bar until you've tried... The problem has to do with scoping. When the compiler begins to compile the inner block (where s1 and s2 are declared) it places those variables in the symbol table, linked into the list of symbols for that scope level. Fine. When the compiler comes upon the goto statements, it places the destination symbol, ``cleanup'' into the symbol tables as an undefined extern label. Now, when the compiler finishes compiling this inner scope block it removes all the block-local symbols from the symbol table. Their slots in the symbol table are therefore free. One line later, the compiler comes upon a label, ``cleanup:''. It hashes the name, and gets a symbol table index. Using the index, it starts searching the linear symbol array for 1) a label named ``cleanup'' or 2) an empty symbol table slot well, normally it would have to find no. 1 first. But since the presence of the small scope block caused the compiler to allocate and then de-allocate several symbol table slots, the compiler ends up finding a free slot first. For instance, the undefined extern label ``cleanup'' might have been placed at 1875, after ``cp'' at 1874 (assuming they hash near eachother). Well, ``cp'' was removed from the symbol table, so the search for ``cleanup'' starting at hash index 1800 will find the empty slot at 1874 before it finds the correct occupied slot at 1875. Hmmmm! Ah Hah! This is an epiphenomenon arising from the linear search collision scheme used in PCC2-based C compilers. Naturally, this is only likely to occur when the symbol table is close to full, so that collisions and (I call them) anti-collisions happen often. Whewee! No wonder I had trouble duplicating the bug! Has anybody else ever observed anything like this? Is the code wrong? Is this compiler simply a poor one? I would like to fix it, but I cannot simply give the compiler a more sophisticated symtab management scheme, because this linear searching discipline is hardcoded into several parts of the compiler. Arghh! Comments? -- ...nz (Neal Ziring @ ATT-BL Holmdel, x2354, 3H-437) "You can fit an infinite number of wires into this junction box, but we usually don't go that far in practice." London Electric Co. Worker, 1880s
chris@mimsy.UUCP (Chris Torek) (09/30/87)
In article <129@hotlg.ATT> nz@hotlg.ATT (Neal Ziring) writes: >One of the developers came upon a very interesting problem with >our C cross-compiler the other day. The compiler runs on a VAX >(SysV.2) and produces code for the M68000/10. ... [A compile] bombed >with a message about the symbol ``cleanup'' being undefined. That >symbol was his goto label -- and it appeared right there in the >file. ... Why was it that I, the compiler support person, could >not duplicate the problem when I tried to write some little test >programs. Why was it that whenever the number of declarations in >the dozens of #included header files was changed, the problem would >go away? Why was it that other files with similar structure did >not evoke the fatal-error behaviour? It sounds almost as though someone copied my `clearst' speedup for the 4.2BSD VAX PCC. There is a bug in it. It shows up only with goto labels, and possibly `extern' declarations that appear inside functions, and only when the symbol table becomes moderately full and the goto label hashes to the same slot as an already-declared local variable. When the local variable is removed from the symbol table because it went out of scope, displaced symbols (i.e., the goto label) are moved back to their proper slots. Alas, I put the addresses of the symbols on a scope chain (`schain') and forgot to alter the appropriate chain as well. My bug usually results in compiler error: schain botch rather than a bogus compile. Sorry about that. (Someone will post a fix soon.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris