Add the SH_TIMING_RESTRICTIONS compile flag and dependency graph implementation.

Description of the algorithm:
http://code.google.com/p/mvujovic/wiki/ShaderControlFlowAnalysis

This flag is one potential solution to timing attacks on textures containing cross-domain content
or user agent data.
This kind of analysis could be useful for both WebGL and CSS Shaders.

The SH_TIMING_RESTRICTIONS flag will reject a shader if it uses texture dependent data to affect
control flow.

Other ways of affecting shader timing such as using NaNs in basic arithmetic operations or using
built-in functions (e.g. atan) with different inputs are still under investigation.

Issue=329
Review URL: http://codereview.appspot.com/6195062/



git-svn-id: https://angleproject.googlecode.com/svn/trunk@1101 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/depgraph/DependencyGraph.cpp b/src/compiler/depgraph/DependencyGraph.cpp
new file mode 100644
index 0000000..0f1ae79
--- /dev/null
+++ b/src/compiler/depgraph/DependencyGraph.cpp
@@ -0,0 +1,109 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/depgraph/DependencyGraph.h"
+#include "compiler/depgraph/DependencyGraphBuilder.h"
+
+TDependencyGraph::TDependencyGraph(TIntermNode* intermNode)
+{
+    TDependencyGraphBuilder::build(intermNode, this);
+}
+
+TDependencyGraph::~TDependencyGraph()
+{
+    for (TGraphNodeVector::const_iterator iter = mAllNodes.begin(); iter != mAllNodes.end(); ++iter)
+    {
+        TGraphNode* node = *iter;
+        delete node;
+    }
+}
+
+TGraphSymbol* TDependencyGraph::getGlobalSymbolByName(const TString& name) const
+{
+    TSymbolNameMap::const_iterator iter = mGlobalSymbolMap.find(name);
+    if (iter == mGlobalSymbolMap.end())
+        return NULL;
+
+    TSymbolNamePair pair = *iter;
+    TGraphSymbol* symbol = pair.second;
+    return symbol;
+}
+
+TGraphArgument* TDependencyGraph::createArgument(TIntermAggregate* intermFunctionCall,
+                                                 int argumentNumber)
+{
+    TGraphArgument* argument = new TGraphArgument(intermFunctionCall, argumentNumber);
+    mAllNodes.push_back(argument);
+    return argument;
+}
+
+TGraphFunctionCall* TDependencyGraph::createFunctionCall(TIntermAggregate* intermFunctionCall)
+{
+    TGraphFunctionCall* functionCall = new TGraphFunctionCall(intermFunctionCall);
+    mAllNodes.push_back(functionCall);
+    if (functionCall->getIntermFunctionCall()->isUserDefined())
+        mUserDefinedFunctionCalls.push_back(functionCall);
+    return functionCall;
+}
+
+TGraphSymbol* TDependencyGraph::getOrCreateSymbol(TIntermSymbol* intermSymbol, bool isGlobalSymbol)
+{
+    TSymbolIdMap::const_iterator iter = mSymbolIdMap.find(intermSymbol->getId());
+
+    TGraphSymbol* symbol = NULL;
+
+    if (iter != mSymbolIdMap.end()) {
+        TSymbolIdPair pair = *iter;
+        symbol = pair.second;
+    } else {
+        symbol = new TGraphSymbol(intermSymbol);
+        mAllNodes.push_back(symbol);
+
+        TSymbolIdPair pair(intermSymbol->getId(), symbol);
+        mSymbolIdMap.insert(pair);
+
+        if (isGlobalSymbol) {
+            // We map all symbols in the global scope by name, so traversers of the graph can
+            // quickly start searches at global symbols with specific names.
+            TSymbolNamePair pair(intermSymbol->getSymbol(), symbol);
+            mGlobalSymbolMap.insert(pair);
+        }
+    }
+
+    return symbol;
+}
+
+TGraphSelection* TDependencyGraph::createSelection(TIntermSelection* intermSelection)
+{
+    TGraphSelection* selection = new TGraphSelection(intermSelection);
+    mAllNodes.push_back(selection);
+    return selection;
+}
+
+TGraphLoop* TDependencyGraph::createLoop(TIntermLoop* intermLoop)
+{
+    TGraphLoop* loop = new TGraphLoop(intermLoop);
+    mAllNodes.push_back(loop);
+    return loop;
+}
+
+TGraphLogicalOp* TDependencyGraph::createLogicalOp(TIntermBinary* intermLogicalOp)
+{
+    TGraphLogicalOp* logicalOp = new TGraphLogicalOp(intermLogicalOp);
+    mAllNodes.push_back(logicalOp);
+    return logicalOp;
+}
+
+const char* TGraphLogicalOp::getOpString() const
+{
+    const char* opString = NULL;
+    switch (getIntermLogicalOp()->getOp()) {
+        case EOpLogicalAnd: opString = "and"; break;
+        case EOpLogicalOr: opString = "or"; break;
+        default: opString = "unknown"; break;
+    }
+    return opString;
+}