[comp.lang.c] More on Microware C goto bug

knudsen@ihwpt.UUCP (02/06/87)

Last nite I used the -ca switch to see how Microware C
is screwing up the stack on goto's.

First of all, this C does not use the stack for any
control structures that I've examined.
However, since any block of code in {} can introduce
its own local vars, this C regards ANY goto as potentially
hosing up the stack.  Since the compiler is so nearsighted,
it does certain things whenever it sees a goto or a label
("come-from").

The first technique used is basically OK.  Before jumping
on a goto, the compiler sets the stack back to when the
function was entered, ie, it pops (nondestructively) the
automatic vars plus any added in {} blocks.
Each label entry puts the stack back to where it would be
if that code were just flowed into (flowing jumps around
the entry code).  This overhead goes with every goto and
label in your source code, but is just one LEAS instr.
This simple scheme is used, for example, when doing a
goto to another label within a list of cases in a switch,
and probably any time that the label and goto are at the
same level of {}, tho of course NOTHING needs to be done
in such cases.  But no real harm is done.

But then they overthought the plumbing and thought up
a fancier scheme that isnt needed and isn't even
implemented correctly.  In the case of my
backwards goto out of a switch-case structure, they
compute what the stack pointer was at function entry, but
put it in the X register instead of S.  That is, they do
	LEAX n,S	where n is the current depth.
Then at the label entry they do
	LEAS 0,X	equivalent to TFR X,S
when they *should* have done
	LEAS n,X
So this explains why the stack pointer "walks" upward each
time the goto recycles.

Why Microware didn't stick with their first scheme I don't know.
Looks like the second is an attempt to preserve the stack state
at the goto, but I don't see why this should be needed.
If they're smart enuf to understand why, why did they bugger up
such a simple case?

Until Microware fixes this (Level II maybe??), I suggest:
(1) Don't use gotos across { or }.
(2) If you get catastrophic failures for no good reason,
look for violations of (1) and "instrument" the location of
an auto variable with a printf to check for stack "walk".
(3) Compile with the -a or -ac options and check your assembler
input closely whenever you have any doubts about some non-trivial
expression or statement.  This compiler cannot be trusted!
Someone reported trouble with
	&(array[i])
but I've had no trouble there.
-- 
Mike J Knudsen    ...ihnp4!ihwpt!knudsen
"It's like trying to get to sleep at the Intergalactic
Spaceport Hotel -- waiting for the being in the room above
to drop the Nth shoe, and you don't even know what N is."