ControlFlowGraph::BlockPointerVector ControlFlowGraph::pre_order_sequence() { typedef std::unordered_set<iterator> BlockSet; typedef std::stack<iterator> Stack; BlockSet visited; BlockPointerVector sequence; Stack stack; if (!empty()) { stack.push(get_entry_block()); visited.insert(get_entry_block()); } while (!stack.empty()) { iterator current = stack.top(); stack.pop(); sequence.push_back(current); // favor the fallthrough iterator fallthrough = end(); if (current->has_fallthrough_edge()) { edge_iterator fallthroughEdge = sequence.back()->get_fallthrough_edge(); if (visited.insert(fallthroughEdge->tail).second) { fallthrough = fallthroughEdge->tail; } } for (pointer_iterator block = current->successors.begin(); block != current->successors.end(); ++block) { if (visited.insert(*block).second) { stack.push(*block); } } if (fallthrough != end()) { stack.push(fallthrough); } } return sequence; }
ControlFlowGraph::BlockPointerVector ControlFlowGraph::executable_sequence() { typedef std::unordered_set<iterator> BlockSet; BlockPointerVector sequence; BlockSet unscheduled; for(iterator i = begin(); i != end(); ++i) { unscheduled.insert(i); } report("Getting executable sequence."); sequence.push_back(get_entry_block()); unscheduled.erase(get_entry_block()); report(" added " << get_entry_block()->label()); while (!unscheduled.empty()) { if (sequence.back()->has_fallthrough_edge()) { edge_iterator fallthroughEdge = sequence.back()->get_fallthrough_edge(); if (unscheduled.count(fallthroughEdge->tail) != 0) { sequence.push_back(fallthroughEdge->tail); unscheduled.erase(fallthroughEdge->tail); } } else { // find a new block, favor branch targets over random blocks iterator next = *unscheduled.begin(); for(edge_pointer_iterator edge = sequence.back()->out_edges.begin(); edge != sequence.back()->out_edges.end(); ++edge) { if(unscheduled.count((*edge)->tail) != 0) { next = (*edge)->tail; } } // rewind through fallthrough edges to find the beginning of the // next chain of fall throughs report(" restarting at " << next->label()); bool rewinding = true; while (rewinding) { rewinding = false; for (edge_pointer_iterator edge = next->in_edges.begin(); edge != next->in_edges.end(); ++edge) { if ((*edge)->type == Edge::FallThrough) { assertM(unscheduled.count((*edge)->head) != 0, (*edge)->head->label() << " has multiple fallthrough branches."); next = (*edge)->head; report(" rewinding to " << next->label() ); rewinding = true; break; } } } sequence.push_back(next); unscheduled.erase(next); } report(" added " << sequence.back()->label()); } return sequence; }