next up previous
Next: dismantle Up: Predefined Phases Previous: ccobj

cfg

The cfg phase first dismantles the C code into MIR form (see Section 4) and then creates a control flow graph using a basicblockNode to represent a basic block. The graph edges are referenced by the succs() and preds() STL lists in each basicblockNode; each procNode contains a body whose statement list (stmts()) is just a list of basicblockNodes that are the nodes in the CFG. The C code is also commented to show the pred/succ relationship among the blocks. For example, consider the following code:

int main(int argc, char ** argv) {
  int a, b, c;

  for (a = 1; a<=10; a++) {
    c = a % 2;
    if (c) {
      b = a * 2;
    } else {
      b = a;
    }
  }
}

After processing with the -cfg flag, the above code is translated to the following:

int main(int argc, char * * argv)
{
  int a;
  int b;
  int c;
  int __T7;
  int __T10;
  
  {
    /* # 1: preds( ) succs( 2 ) */
    a = 1;
    goto __T1;
  }
  {
    /* # 2: preds( 1 6 ) succs( 3 7 ) */
    __T1:
      ;
    if (a <= 10) goto __T3;
    goto __T2;
  }
  {
    /* # 3: preds( 2 ) succs( 4 5 ) */
    __T3:
      ;
    c = a % 2;
    if (c == 0) goto __T5;
    goto __T12;
  }
  {
    /* # 4: preds( 3 ) succs( 6 ) */
    __T12:
      ;
    b = a * 2;
    goto __T4;
  }
  {
    /* # 5: preds( 3 ) succs( 6 ) */
    __T5:
      ;
    b = a;
    goto __T4;
  }
  {
    /* # 6: preds( 4 5 ) succs( 2 ) */
    __T4:
      ;
    __T10 = a;
    a = a + 1;
    goto __T1;
  }
  {
    /* # 7: preds( 2 ) succs( ) */
    __T2:
      ;
    return __T7;
  }
}

Once the control flow graph has been generated, each function is guaranteed to have exactly one exit, and that exit is the last block in the list of statements. See cfg.h for information about invoking the control flow graph generator programmatically from C++ code.



Adam C. Brown 2006-01-26