void G_addEdge(G_node from, G_node to) { assert(from); assert(to); assert(from->mygraph == to->mygraph); if (G_goesTo(from, to)) return; to->preds=G_NodeList(from, to->preds); from->succs=G_NodeList(to, from->succs); }
/* generic creation of G_node */ G_node G_Node(G_graph g, void *info) {G_node n = (G_node)checked_malloc(sizeof *n); G_nodeList p = G_NodeList(n, NULL); assert(g); n->mygraph=g; n->mykey=g->nodecount++; if (g->mylast==NULL) g->mynodes=g->mylast=p; else g->mylast = g->mylast->tail = p; n->succs=NULL; n->preds=NULL; n->info=info; return n; }
G_graph FG_AssemFlowGraph(AS_instrList il) { UD_init(); //(I) Iterate over the entire instruction list AS_instr instr = NULL; G_node prev = NULL; G_node curr = NULL; G_graph graph = G_Graph(); G_nodeList jumpList = NULL; G_nodeList jumpListHead = NULL; for(; il!=NULL; il=il->tail){ instr = il->head; if(instr!=NULL){ //1) create a node (and put it into the graph), using the // instruction as the associated info. curr = G_Node(graph, instr); //2) special handling int type = IT_COMMON; Temp_tempList defs = NULL; Temp_tempList uses = NULL; switch(instr->kind) { case I_OPER: // Check if it's a JUMP instruction // We do this check here by looking if As_target is null, // instead of inspecting the assembly op (j, beq, ...) if(instr->u.OPER.jumps!=NULL && instr->u.OPER.jumps->labels!=NULL){ type = IT_JUMP; // put this instruction into a separate list if(jumpList==NULL){ jumpList = G_NodeList(curr, NULL); jumpListHead = jumpList; } else { jumpList->tail = G_NodeList(curr, NULL); jumpList = jumpList->tail; } } defs = instr->u.OPER.dst; uses = instr->u.OPER.src; break; case I_LABEL: //2.2) label should be also saved in the label-node list for (II) LT_enter(instr->u.LABEL.label, curr); break; case I_MOVE: //2.3) it's a move instruction type = IT_MOVE; defs = instr->u.MOVE.dst; uses = instr->u.MOVE.src; break; } //3) put information into table UD_enter(curr, UDInfo(uses, defs, type == IT_MOVE)); //4) link with the previous node for falling through, if possible. // Note that prev is NULL if the previous instruction is a JUMP. if(prev!=NULL){ G_addEdge(prev, curr); } //5) set as previous node for next time of iteration prev = (type!=IT_JUMP)?curr:NULL; } } //(II) Iterate over the list that has all the JUMP instruction collected. Temp_labelList labels; for(; jumpListHead!=NULL; jumpListHead=jumpListHead->tail){ curr = jumpListHead->head; labels = ((AS_instr)G_nodeInfo(curr))->u.OPER.jumps->labels;//no need to check its nullity again Temp_label label; G_node dest; // for each target it may jump to, add a corresponding edge in the graph for(;labels!=NULL;labels=labels->tail){ label = labels->head; if(label!=NULL){ // quickly retieve the target node using the label-node table dest = LT_lookup(label); // establish edge between this node and its jump target G_addEdge(curr, dest); } } } return graph; }