[tree-ssa] computed gotos
Daniel Berlin
dberlin@dberlin.org
Fri Jan 24 21:01:00 GMT 2003
On Friday, January 24, 2003, at 03:09 PM, law@redhat.com wrote:
>
> This allows us to handle computed gotos in the presense of static
> initializers containing label addresses. Fun fun.
If you actually want to *simplify* computed gotos (whose labels are
local to the function), you can transform them into a switch statement
by assigning each label whose address is taken some small integer
number.
CIL does this (http://manju.cs.berkeley.edu/cil)
" Labels as values and computed goto. This allows a program to take the
address of a label and to manipulate it as any value and also to
perform a computed goto. We compile this by assigning each label whose
address is taken a small integer that acts as its address. Every
computed goto in the body of the function is replaced with a switch
statement. If you want to invoke the label from another function, you
are on your own (the gcc documentation says the same.) "
That way, you don't have to handle the common case specially in the cfg
builder.
An example transformation, from the CIL manual:
static void *jtab[2]; // A jump table
static int doit(int x){
static int jtab_init = 0;
if(!jtab_init) { // Initialize the jump table
jtab[0] = &&lbl1;
jtab[1] = &&lbl2;
jtab_init = 1;
}
goto *jtab[x]; // Jump through the table
lbl1:
return 0;
lbl2:
return 1;
}
int main(void){
if (doit(0) != 0) exit(1);
if (doit(1) != 1) exit(1);
exit(0);
}
becomes
/* Generated by CIL v. 1.0.5 */
/* print_CIL_Input is true */
# 1 "cilcode.tmp/ex33.c"
static void *jtab[2] ;
# 4
static int doit(int x ) ;
# 4 "cilcode.tmp/ex33.c"
static int jtab_init = 0;
# 2 "cilcode.tmp/ex33.c"
static int doit(int x )
{ unsigned int __compgoto ;
{
# 5
if (! jtab_init) {
# 6
jtab[0] = (void *)0;
# 7
jtab[1] = (void *)1;
# 8
jtab_init = 1;
}
# 10
__compgoto = (unsigned int )jtab[x];
# 10
switch (__compgoto) {
case 1:
goto lbl2;
case 0:
goto lbl1;
default:
# 10
(*((int *)0)) = 0;
}
lbl1:
# 12
return (0);
lbl2:
# 14
return (1);
}
}
# 18
extern int ( /* missing proto */ exit)() ;
# 17 "cilcode.tmp/ex33.c"
int main(void)
{ int tmp ;
int tmp___0 ;
{
# 18
tmp = doit(0);
# 18
if (tmp != 0) {
# 18
exit(1);
}
# 19
tmp___0 = doit(1);
# 19
if (tmp___0 != 1) {
# 19
exit(1);
}
# 20
exit(0);
# 20
return (0);
}
}
More information about the Gcc-patches
mailing list