00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027 #include "ShCtrlGraph.hpp"
00028 #include <iostream>
00029 #include <cassert>
00030 #include <vector>
00031 #include "ShBasicBlock.hpp"
00032 #include "ShToken.hpp"
00033 #include "ShTokenizer.hpp"
00034 #include "ShUtility.hpp"
00035 #include "ShParser.hpp"
00036 #include "ShDebug.hpp"
00037
00038 namespace SH {
00039
00040 ShCtrlGraphNode::ShCtrlGraphNode()
00041 : follower(0), m_marked(false)
00042 {
00043 }
00044
00045 ShCtrlGraphNode::~ShCtrlGraphNode() {
00046 }
00047
00048 std::ostream& ShCtrlGraphNode::print(std::ostream& out, int indent) const
00049 {
00050 if (marked()) return out;
00051 mark();
00052
00053 if (block) block->print(out, indent);
00054 if (follower) {
00055 shPrintIndent(out, indent);
00056 out << "->" << std::endl;
00057 follower->print(out, indent + 2);
00058 }
00059 for (SuccessorList::const_iterator I = successors.begin();
00060 I != successors.end(); ++I) {
00061 shPrintIndent(out, indent);
00062 if (!I->cond.null()) {
00063 out << "[" << I->cond.name() << "]" << std::endl;
00064 }
00065 out << "->" << std::endl;
00066 I->node->print(out, indent + 2);
00067 }
00068 return out;
00069 }
00070
00071 std::ostream& ShCtrlGraphNode::graphvizDump(std::ostream& out) const
00072 {
00073 if (marked()) return out;
00074 mark();
00075 out << "\"" << this << "\" ";
00076 if (block) {
00077 out << " [label=\"";
00078 block->graphvizDump(out);
00079 out << "\", shape=box]";
00080 } else {
00081 out << " [label=\"\", shape=circle, height=0.25]";
00082 }
00083 out << ";" << std::endl;
00084
00085 for (SuccessorList::const_iterator I = successors.begin();
00086 I != successors.end(); ++I) {
00087 I->node->graphvizDump(out);
00088 out << "\"" << this << "\" ";
00089 out << "-> ";
00090 out << "\"" << I->node.object() << "\" ";
00091
00092 out << "[style=dashed, label=\"" << I->cond.name() << "\"]";
00093 out << ";" << std::endl;
00094 }
00095
00096 if (follower) {
00097 follower->graphvizDump(out);
00098 out << "\"" << this << "\" ";
00099 out << "-> ";
00100 out << "\"" << follower.object() << "\";" << std::endl;
00101 }
00102
00103 return out;
00104 }
00105
00106 bool ShCtrlGraphNode::marked() const
00107 {
00108 return m_marked;
00109 }
00110
00111 void ShCtrlGraphNode::mark() const
00112 {
00113 m_marked = true;
00114 }
00115
00116 void ShCtrlGraphNode::clearMarked() const
00117 {
00118 if (!marked()) return ;
00119 m_marked = false;
00120
00121 if (follower) follower->clearMarked();
00122
00123 for (SuccessorList::const_iterator I = successors.begin();
00124 I != successors.end(); ++I) {
00125 I->node->clearMarked();
00126 }
00127 }
00128
00129 void ShCtrlGraphNode::append(const ShPointer<ShCtrlGraphNode>& node)
00130 {
00131 if (!node) return;
00132 assert(!follower);
00133 follower = node;
00134 }
00135
00136 void ShCtrlGraphNode::append(const ShPointer<ShCtrlGraphNode>& node,
00137 ShVariable cond)
00138 {
00139 if (node) successors.push_back(ShCtrlGraphBranch(node, cond));
00140 }
00141
00142 ShCtrlGraphNodePtr ShCtrlGraphNode::split(ShBasicBlock::ShStmtList::iterator stmt)
00143 {
00144
00145
00146 ShCtrlGraphNode *after = new ShCtrlGraphNode();
00147 after->successors = successors;
00148 after->follower = follower;
00149 successors.clear();
00150 follower = 0;
00151
00152
00153 after->predecessors.push_back(this);
00154 this->follower = after;
00155
00156
00157 after->block = new ShBasicBlock();
00158 after->block->splice(after->block->begin(), block->m_statements, stmt);
00159
00160 return after;
00161 }
00162
00163 ShCtrlGraphBranch::ShCtrlGraphBranch(const ShPointer<ShCtrlGraphNode>& node,
00164 ShVariable cond)
00165 : node(node), cond(cond)
00166 {
00167 }
00168
00169 ShCtrlGraph::ShCtrlGraph(ShCtrlGraphNodePtr head, ShCtrlGraphNodePtr tail)
00170 : m_entry(head),
00171 m_exit(tail)
00172 {
00173 }
00174
00175 ShCtrlGraph::ShCtrlGraph(ShBlockListPtr blocks)
00176 : m_entry(new ShCtrlGraphNode()),
00177 m_exit(new ShCtrlGraphNode())
00178 {
00179 ShCtrlGraphNodePtr head, tail;
00180
00181 ShParser::parse(head, tail, blocks);
00182
00183 if(!head && !tail) {
00184 m_entry->append(m_exit);
00185 } else {
00186 SH_DEBUG_ASSERT(head && tail);
00187 m_entry->append(head);
00188 tail->append(m_exit);
00189 }
00190 }
00191
00192 ShCtrlGraph::~ShCtrlGraph()
00193 {
00194 }
00195
00196 ShCtrlGraphNodePtr ShCtrlGraph::entry() const
00197 {
00198 return m_entry;
00199 }
00200
00201 ShCtrlGraphNodePtr ShCtrlGraph::exit() const
00202 {
00203 return m_exit;
00204 }
00205
00206 ShCtrlGraphNodePtr ShCtrlGraph::prependEntry() {
00207 ShCtrlGraphNodePtr newEntry = new ShCtrlGraphNode();
00208 ShCtrlGraphNodePtr oldEntry = m_entry;
00209 newEntry->append(oldEntry);
00210 newEntry->mark();
00211
00212 if( oldEntry->block ) {
00213 SH_DEBUG_WARN( "Old entry to control graph did not have an empty block!");
00214 } else {
00215 oldEntry->block = new ShBasicBlock();
00216 }
00217 m_entry = newEntry;
00218 return oldEntry;
00219 }
00220
00221 ShCtrlGraphNodePtr ShCtrlGraph::appendExit() {
00222 ShCtrlGraphNodePtr newExit = new ShCtrlGraphNode();
00223 ShCtrlGraphNodePtr oldExit = m_exit;
00224 oldExit->append(newExit);
00225
00226 if( oldExit->block ) {
00227 SH_DEBUG_WARN( "Old exit to control graph did not have an empty block!");
00228 } else {
00229 oldExit->block = new ShBasicBlock();
00230 }
00231 m_exit = newExit;
00232 return oldExit;
00233 }
00234
00235 std::ostream& ShCtrlGraph::print(std::ostream& out, int indent) const
00236 {
00237 if (m_entry) {
00238 m_entry->clearMarked();
00239 m_entry->print(out, indent);
00240 }
00241
00242 return out;
00243 }
00244
00245 std::ostream& ShCtrlGraph::graphvizDump(std::ostream& out) const
00246 {
00247 out << "digraph control {" << std::endl;
00248
00249 if (m_entry) {
00250 m_entry->clearMarked();
00251 m_entry->graphvizDump(out);
00252 }
00253
00254 out << "}" << std::endl;
00255 return out;
00256 }
00257
00258 struct ClearPreds {
00259 void operator()(ShCtrlGraphNodePtr node) {
00260 if (!node) return;
00261 node->predecessors.clear();
00262 }
00263 };
00264
00265 struct ComputePreds {
00266 void operator()(ShCtrlGraphNode* node) {
00267 if (!node) return;
00268
00269 for (ShCtrlGraphNode::SuccessorList::iterator I = node->successors.begin();
00270 I != node->successors.end(); ++I) {
00271 if (I->node) I->node->predecessors.push_back(node);
00272 }
00273 if (node->follower) node->follower->predecessors.push_back(node);
00274 }
00275 };
00276
00277
00278 void ShCtrlGraph::computePredecessors()
00279 {
00280 ClearPreds clear;
00281 dfs(clear);
00282
00283 ComputePreds comp;
00284 dfs(comp);
00285 }
00286
00287 typedef std::map<ShCtrlGraphNodePtr, ShCtrlGraphNodePtr> CtrlGraphCopyMap;
00288
00289 struct CtrlGraphCopier {
00290 CtrlGraphCopier(CtrlGraphCopyMap& copyMap)
00291 : copyMap(copyMap)
00292 {
00293 }
00294
00295 void operator()(ShCtrlGraphNodePtr node) {
00296 if (!node) return;
00297 ShCtrlGraphNodePtr newNode = new ShCtrlGraphNode(*node);
00298 copyMap[node] = newNode;
00299 }
00300
00301 CtrlGraphCopyMap& copyMap;
00302 };
00303
00304 void ShCtrlGraph::copy(ShCtrlGraphNodePtr& newHead, ShCtrlGraphNodePtr& newTail) const
00305 {
00306 CtrlGraphCopyMap copyMap;
00307 copyMap[0] = 0;
00308
00309 CtrlGraphCopier copier(copyMap);
00310 SH_DEBUG_ASSERT(m_entry);
00311 SH_DEBUG_ASSERT(m_exit);
00312 m_entry->clearMarked();
00313 m_entry->dfs(copier);
00314
00315
00316 for (CtrlGraphCopyMap::iterator I = copyMap.begin(); I != copyMap.end(); ++I) {
00317 ShCtrlGraphNodePtr node = I->second;
00318 if (!node) continue;
00319 for (ShCtrlGraphNode::SuccessorList::iterator J = node->successors.begin();
00320 J != node->successors.end(); ++J) {
00321 J->node = copyMap[J->node];
00322 }
00323 node->follower = copyMap[node->follower];
00324 if (node->block) {
00325 ShBasicBlockPtr new_block = new ShBasicBlock(*node->block);
00326 node->block = new_block;
00327 }
00328 }
00329 newHead = copyMap[m_entry];
00330 newTail = copyMap[m_exit];
00331 SH_DEBUG_ASSERT(newHead);
00332 SH_DEBUG_ASSERT(newTail);
00333
00334 m_entry->clearMarked();
00335 }
00336
00337
00338
00339 }
00340