[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