[comp.lang.c] jumptables

chris@mimsy.UUCP (03/01/87)

In article <545@mntgfx.MENTOR.COM> franka@mntgfx.MENTOR.COM (Frank A.
Adrian) writes:
>Now for my pet peeve.

(Well, *he* spells it right. :-) )

>Why can't you take the address of a label?

Actually, due to what must be considered a bug in 4BSD PCC, you can:

	f()
	{
		int *p;

		/* esablish label name: */
		if (0) goto foo;
		p = foo;
		...

There is a hitch, however:  You cannot `goto p'.  If you are willing
to cheat, it is possible.  See the appended bug ... I mean program.

>[A jump table] is different [from `switch'] in three ways ...

All true enough.

>This construct is not difficult to implement on linkers,

Also true.

>it is not any more hazardous than the goto statement itself,

Not so!  The existing C `goto' can never change function contexts.
Only `longjmp' has this power.  Label assignments, unless they are
severely restricted, one can do non-local `goto's quite easily.
This also means that the label type must carry around a lot of
extra baggage, which has a tendency to destroy much of the efficiency
you thought you were gaining.

>and it introduces a capability into the language which is not
>currently there and for which no fast workaround exists.

True.

>In fact, I wonder why this idea has not been implemented before...

I think it has.

/*
 * Program demonstrating weird jump table.
 *
 * Passes lint.
 */
int *labels[3];

main()
{
	register int *addr;	/* r11 */
	register int i;

#ifdef lint
#define	LABEL(i, l) if (rand()) goto l; else labels[i] = l
#else
#define LABEL(i, l) if (0) goto l; else labels[i] = l
#endif

	LABEL(0, foo);
	LABEL(1, bar);
	LABEL(2, baz);

	i = 0;
loop:
	if (i < 3) {
		addr = labels[i++];
#ifdef lint
		addr = addr;
#endif
		asm("	jmp	(r11)");
		printf("oops\n");
		exit(1);
	}
	printf("done\n");
	exit(0);

foo:
	printf("foo\n");
	goto loop;

bar:
	printf("bar\n");
	goto loop;

baz:
	printf("baz\n");
	goto loop;
}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
UUCP:	seismo!mimsy!chris	ARPA/CSNet:	chris@mimsy.umd.edu

franka@mntgfx.UUCP (03/02/87)

In article <5626@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>In article <545@mntgfx.MENTOR.COM> franka@mntgfx.MENTOR.COM (Frank A.
>Adrian) writes:

>>Now for my pet peeve.
>(Well, *he* spells it right. :-) )
Thank you...

>>it is not any more hazardous than the goto statement itself,
>Not so!  The existing C `goto' can never change function contexts.
>Only `longjmp' has this power.  Label assignments, unless they are
>severely restricted, one can do non-local `goto's quite easily.
>This also means that the label type must carry around a lot of
>extra baggage, which has a tendency to destroy much of the efficiency
>you thought you were gaining.

Ah yes, the fly in the ointment.  I had for gotten about the nasty little
non-localities one can introduce with this feature.  I'd say just don't
let label arrays be passed or used non-locally, but this introduces another
non-orthogonal feature into the language and I hate non-orthogonal constructs
even more than the inconvenience of assembly code.  I'll "cry uncle" on this
one.

Frank Adrian
Mentor Graphics, Inc.

Eddie.Wyatt@ius2.cs.cmu.edu.UUCP (03/11/87)

   To follow is the assemble language generated by a C compiler running
on a Vax 780 (Unix os of course) for a case statement.


LL0:
	.data
	.text
	.align	1
	.globl	_main
_main:
	.word	L12
	jbr 	L14
L15:
	movl	-4(fp),r0
	jbr 	L17
L18:
	movl	-12(fp),-8(fp)
	jbr 	L16
L19:
	movl	-16(fp),-20(fp)
	jbr 	L16
L20:
	movl	-20(fp),-16(fp)
	jbr 	L16
L21:
	movl	-8(fp),-16(fp)
	jbr 	L16
L22:
	movl	-8(fp),-24(fp)
	jbr 	L16
L23:
	movl	-24(fp),-16(fp)
	jbr 	L16
L17:
	casel	r0,$0,$5
L24:
	.word	L18-L24
	.word	L19-L24
	.word	L20-L24
	.word	L21-L24
	.word	L22-L24
	.word	L23-L24
L25:
L16:
	ret
	.set	L12,0x0
L14:
	subl2	$24,sp
	jbr 	L15
	.data


Original code

main()
    {
    int c;
    int h, k, j, i, m;

    switch (c)
	{
        case 0:
	    h = k;
	    break;
        case 1:
	    i = j;
	    break;
        case 2:
	    j = i;
	    break;
        case 3:
	    j  = h;
	    break;
        case 4:
	    m  = h;
	    break;
        case 5:
	    j  = m;
	    break;
	}
    }


Note that the vax has a special case instruction.  

  The answer to your question of why you can't have jump tables is
that it is up to the C compiler to make such optimizations that may be machine
depended.
  May I also ask have you checked the code that your C compiler has generated
to make sure it is not generating direct threaded code for case statements?
As I have been told, the C compiler for the Suns does.


					Eddie Wyatt
					Research Programming (CMU)
					edw@ius1.cs.cmu.edu