PageRenderTime 56ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/qt/qtbase/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp

https://gitlab.com/x33n/phantomjs
C++ | 227 lines | 159 code | 41 blank | 27 comment | 39 complexity | 41a224233ed33d259ff0c5f68573bdb2 MD5 | raw file
  1. //
  2. // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
  3. // Use of this source code is governed by a BSD-style license that can be
  4. // found in the LICENSE file.
  5. //
  6. #include "compiler/translator/depgraph/DependencyGraphBuilder.h"
  7. void TDependencyGraphBuilder::build(TIntermNode* node, TDependencyGraph* graph)
  8. {
  9. TDependencyGraphBuilder builder(graph);
  10. builder.build(node);
  11. }
  12. bool TDependencyGraphBuilder::visitAggregate(Visit visit, TIntermAggregate* intermAggregate)
  13. {
  14. switch (intermAggregate->getOp()) {
  15. case EOpFunction: visitFunctionDefinition(intermAggregate); break;
  16. case EOpFunctionCall: visitFunctionCall(intermAggregate); break;
  17. default: visitAggregateChildren(intermAggregate); break;
  18. }
  19. return false;
  20. }
  21. void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAggregate)
  22. {
  23. // Currently, we do not support user defined functions.
  24. if (intermAggregate->getName() != "main(")
  25. return;
  26. visitAggregateChildren(intermAggregate);
  27. }
  28. // Takes an expression like "f(x)" and creates a dependency graph like
  29. // "x -> argument 0 -> function call".
  30. void TDependencyGraphBuilder::visitFunctionCall(TIntermAggregate* intermFunctionCall)
  31. {
  32. TGraphFunctionCall* functionCall = mGraph->createFunctionCall(intermFunctionCall);
  33. // Run through the function call arguments.
  34. int argumentNumber = 0;
  35. TIntermSequence& intermArguments = intermFunctionCall->getSequence();
  36. for (TIntermSequence::const_iterator iter = intermArguments.begin();
  37. iter != intermArguments.end();
  38. ++iter, ++argumentNumber)
  39. {
  40. TNodeSetMaintainer nodeSetMaintainer(this);
  41. TIntermNode* intermArgument = *iter;
  42. intermArgument->traverse(this);
  43. if (TParentNodeSet* argumentNodes = mNodeSets.getTopSet()) {
  44. TGraphArgument* argument = mGraph->createArgument(intermFunctionCall, argumentNumber);
  45. connectMultipleNodesToSingleNode(argumentNodes, argument);
  46. argument->addDependentNode(functionCall);
  47. }
  48. }
  49. // Push the leftmost symbol of this function call into the current set of dependent symbols to
  50. // represent the result of this function call.
  51. // Thus, an expression like "y = f(x)" will yield a dependency graph like
  52. // "x -> argument 0 -> function call -> y".
  53. // This line essentially passes the function call node back up to an earlier visitAssignment
  54. // call, which will create the connection "function call -> y".
  55. mNodeSets.insertIntoTopSet(functionCall);
  56. }
  57. void TDependencyGraphBuilder::visitAggregateChildren(TIntermAggregate* intermAggregate)
  58. {
  59. TIntermSequence& sequence = intermAggregate->getSequence();
  60. for(TIntermSequence::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter)
  61. {
  62. TIntermNode* intermChild = *iter;
  63. intermChild->traverse(this);
  64. }
  65. }
  66. void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol)
  67. {
  68. // Push this symbol into the set of dependent symbols for the current assignment or condition
  69. // that we are traversing.
  70. TGraphSymbol* symbol = mGraph->getOrCreateSymbol(intermSymbol);
  71. mNodeSets.insertIntoTopSet(symbol);
  72. // If this symbol is the current leftmost symbol under an assignment, replace the previous
  73. // leftmost symbol with this symbol.
  74. if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) {
  75. mLeftmostSymbols.pop();
  76. mLeftmostSymbols.push(symbol);
  77. }
  78. }
  79. bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary)
  80. {
  81. TOperator op = intermBinary->getOp();
  82. if (op == EOpInitialize || intermBinary->isAssignment())
  83. visitAssignment(intermBinary);
  84. else if (op == EOpLogicalAnd || op == EOpLogicalOr)
  85. visitLogicalOp(intermBinary);
  86. else
  87. visitBinaryChildren(intermBinary);
  88. return false;
  89. }
  90. void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment)
  91. {
  92. TIntermTyped* intermLeft = intermAssignment->getLeft();
  93. if (!intermLeft)
  94. return;
  95. TGraphSymbol* leftmostSymbol = NULL;
  96. {
  97. TNodeSetMaintainer nodeSetMaintainer(this);
  98. {
  99. TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mLeftSubtree);
  100. intermLeft->traverse(this);
  101. leftmostSymbol = mLeftmostSymbols.top();
  102. // After traversing the left subtree of this assignment, we should have found a real
  103. // leftmost symbol, and the leftmost symbol should not be a placeholder.
  104. ASSERT(leftmostSymbol != &mLeftSubtree);
  105. ASSERT(leftmostSymbol != &mRightSubtree);
  106. }
  107. if (TIntermTyped* intermRight = intermAssignment->getRight()) {
  108. TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
  109. intermRight->traverse(this);
  110. }
  111. if (TParentNodeSet* assignmentNodes = mNodeSets.getTopSet())
  112. connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol);
  113. }
  114. // Push the leftmost symbol of this assignment into the current set of dependent symbols to
  115. // represent the result of this assignment.
  116. // An expression like "a = (b = c)" will yield a dependency graph like "c -> b -> a".
  117. // This line essentially passes the leftmost symbol of the nested assignment ("b" in this
  118. // example) back up to the earlier visitAssignment call for the outer assignment, which will
  119. // create the connection "b -> a".
  120. mNodeSets.insertIntoTopSet(leftmostSymbol);
  121. }
  122. void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary* intermLogicalOp)
  123. {
  124. if (TIntermTyped* intermLeft = intermLogicalOp->getLeft()) {
  125. TNodeSetPropagatingMaintainer nodeSetMaintainer(this);
  126. intermLeft->traverse(this);
  127. if (TParentNodeSet* leftNodes = mNodeSets.getTopSet()) {
  128. TGraphLogicalOp* logicalOp = mGraph->createLogicalOp(intermLogicalOp);
  129. connectMultipleNodesToSingleNode(leftNodes, logicalOp);
  130. }
  131. }
  132. if (TIntermTyped* intermRight = intermLogicalOp->getRight()) {
  133. TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
  134. intermRight->traverse(this);
  135. }
  136. }
  137. void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary* intermBinary)
  138. {
  139. if (TIntermTyped* intermLeft = intermBinary->getLeft())
  140. intermLeft->traverse(this);
  141. if (TIntermTyped* intermRight = intermBinary->getRight()) {
  142. TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
  143. intermRight->traverse(this);
  144. }
  145. }
  146. bool TDependencyGraphBuilder::visitSelection(Visit visit, TIntermSelection* intermSelection)
  147. {
  148. if (TIntermNode* intermCondition = intermSelection->getCondition()) {
  149. TNodeSetMaintainer nodeSetMaintainer(this);
  150. intermCondition->traverse(this);
  151. if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) {
  152. TGraphSelection* selection = mGraph->createSelection(intermSelection);
  153. connectMultipleNodesToSingleNode(conditionNodes, selection);
  154. }
  155. }
  156. if (TIntermNode* intermTrueBlock = intermSelection->getTrueBlock())
  157. intermTrueBlock->traverse(this);
  158. if (TIntermNode* intermFalseBlock = intermSelection->getFalseBlock())
  159. intermFalseBlock->traverse(this);
  160. return false;
  161. }
  162. bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop)
  163. {
  164. if (TIntermTyped* intermCondition = intermLoop->getCondition()) {
  165. TNodeSetMaintainer nodeSetMaintainer(this);
  166. intermCondition->traverse(this);
  167. if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) {
  168. TGraphLoop* loop = mGraph->createLoop(intermLoop);
  169. connectMultipleNodesToSingleNode(conditionNodes, loop);
  170. }
  171. }
  172. if (TIntermNode* intermBody = intermLoop->getBody())
  173. intermBody->traverse(this);
  174. if (TIntermTyped* intermExpression = intermLoop->getExpression())
  175. intermExpression->traverse(this);
  176. return false;
  177. }
  178. void TDependencyGraphBuilder::connectMultipleNodesToSingleNode(TParentNodeSet* nodes,
  179. TGraphNode* node) const
  180. {
  181. for (TParentNodeSet::const_iterator iter = nodes->begin(); iter != nodes->end(); ++iter)
  182. {
  183. TGraphParentNode* currentNode = *iter;
  184. currentNode->addDependentNode(node);
  185. }
  186. }