Commit ada17c22 by gman@chromium.org

Add expression complexity and call stack depth limits.

git-svn-id: https://angleproject.googlecode.com/svn/trunk@2242 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 5abbd861
...@@ -110,6 +110,10 @@ ...@@ -110,6 +110,10 @@
'LinkIncremental': '2', 'LinkIncremental': '2',
}, },
}, },
'xcode_settings': {
'COPY_PHASE_STRIP': 'NO',
'GCC_OPTIMIZATION_LEVEL': '0',
},
}, # Debug }, # Debug
'Release': { 'Release': {
'inherit_from': ['Common'], 'inherit_from': ['Common'],
......
...@@ -159,7 +159,13 @@ typedef enum { ...@@ -159,7 +159,13 @@ typedef enum {
// vec234, or mat234 type. The ShArrayIndexClampingStrategy enum, // vec234, or mat234 type. The ShArrayIndexClampingStrategy enum,
// specified in the ShBuiltInResources when constructing the // specified in the ShBuiltInResources when constructing the
// compiler, selects the strategy for the clamping implementation. // compiler, selects the strategy for the clamping implementation.
SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000 SH_CLAMP_INDIRECT_ARRAY_BOUNDS = 0x1000,
// This flag limits the complexity of an expression.
SH_LIMIT_EXPRESSION_COMPLEXITY = 0x2000,
// This flag limits the depth of the call stack.
SH_LIMIT_CALL_STACK_DEPTH = 0x4000,
} ShCompileOptions; } ShCompileOptions;
// Defines alternate strategies for implementing array index clamping. // Defines alternate strategies for implementing array index clamping.
...@@ -222,6 +228,12 @@ typedef struct ...@@ -222,6 +228,12 @@ typedef struct
// Selects a strategy to use when implementing array index clamping. // Selects a strategy to use when implementing array index clamping.
// Default is SH_CLAMP_WITH_CLAMP_INTRINSIC. // Default is SH_CLAMP_WITH_CLAMP_INTRINSIC.
ShArrayIndexClampingStrategy ArrayIndexClampingStrategy; ShArrayIndexClampingStrategy ArrayIndexClampingStrategy;
// The maximum complexity an expression can be.
int MaxExpressionComplexity;
// The maximum depth a call stack can be.
int MaxCallStackDepth;
} ShBuiltInResources; } ShBuiltInResources;
// //
......
...@@ -72,8 +72,8 @@ ...@@ -72,8 +72,8 @@
'compiler/ConstantUnion.h', 'compiler/ConstantUnion.h',
'compiler/debug.cpp', 'compiler/debug.cpp',
'compiler/debug.h', 'compiler/debug.h',
'compiler/DetectRecursion.cpp', 'compiler/DetectCallDepth.cpp',
'compiler/DetectRecursion.h', 'compiler/DetectCallDepth.h',
'compiler/Diagnostics.h', 'compiler/Diagnostics.h',
'compiler/Diagnostics.cpp', 'compiler/Diagnostics.cpp',
'compiler/DirectiveHandler.h', 'compiler/DirectiveHandler.h',
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
// //
#include "compiler/BuiltInFunctionEmulator.h" #include "compiler/BuiltInFunctionEmulator.h"
#include "compiler/DetectRecursion.h" #include "compiler/DetectCallDepth.h"
#include "compiler/ForLoopUnroll.h" #include "compiler/ForLoopUnroll.h"
#include "compiler/Initialize.h" #include "compiler/Initialize.h"
#include "compiler/InitializeParseContext.h" #include "compiler/InitializeParseContext.h"
...@@ -104,6 +104,9 @@ TShHandleBase::~TShHandleBase() { ...@@ -104,6 +104,9 @@ TShHandleBase::~TShHandleBase() {
TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
: shaderType(type), : shaderType(type),
shaderSpec(spec), shaderSpec(spec),
maxUniformVectors(0),
maxExpressionComplexity(0),
maxCallStackDepth(0),
fragmentPrecisionHigh(false), fragmentPrecisionHigh(false),
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
builtInFunctionEmulator(type) builtInFunctionEmulator(type)
...@@ -122,6 +125,8 @@ bool TCompiler::Init(const ShBuiltInResources& resources) ...@@ -122,6 +125,8 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
resources.MaxVertexUniformVectors : resources.MaxVertexUniformVectors :
resources.MaxFragmentUniformVectors; resources.MaxFragmentUniformVectors;
maxExpressionComplexity = resources.MaxExpressionComplexity;
maxCallStackDepth = resources.MaxCallStackDepth;
TScopedPoolAllocator scopedAlloc(&allocator, false); TScopedPoolAllocator scopedAlloc(&allocator, false);
// Generate built-in symbol table. // Generate built-in symbol table.
...@@ -185,7 +190,7 @@ bool TCompiler::compile(const char* const shaderStrings[], ...@@ -185,7 +190,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
success = intermediate.postProcess(root); success = intermediate.postProcess(root);
if (success) if (success)
success = detectRecursion(root); success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
success = validateLimitations(root); success = validateLimitations(root);
...@@ -208,6 +213,10 @@ bool TCompiler::compile(const char* const shaderStrings[], ...@@ -208,6 +213,10 @@ bool TCompiler::compile(const char* const shaderStrings[],
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
// Disallow expressions deemed too complex.
if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
success = limitExpressionComplexity(root);
// Call mapLongVariableNames() before collectAttribsUniforms() so in // Call mapLongVariableNames() before collectAttribsUniforms() so in
// collectAttribsUniforms() we already have the mapped symbol names and // collectAttribsUniforms() we already have the mapped symbol names and
// we could composite mapped and original variable names. // we could composite mapped and original variable names.
...@@ -267,24 +276,27 @@ void TCompiler::clearResults() ...@@ -267,24 +276,27 @@ void TCompiler::clearResults()
nameMap.clear(); nameMap.clear();
} }
bool TCompiler::detectRecursion(TIntermNode* root) bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
{ {
DetectRecursion detect; DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
root->traverse(&detect); root->traverse(&detect);
switch (detect.detectRecursion()) { switch (detect.detectCallDepth()) {
case DetectRecursion::kErrorNone: case DetectCallDepth::kErrorNone:
return true; return true;
case DetectRecursion::kErrorMissingMain: case DetectCallDepth::kErrorMissingMain:
infoSink.info.prefix(EPrefixError); infoSink.info.prefix(EPrefixError);
infoSink.info << "Missing main()"; infoSink.info << "Missing main()";
return false; return false;
case DetectRecursion::kErrorRecursion: case DetectCallDepth::kErrorRecursion:
infoSink.info.prefix(EPrefixError); infoSink.info.prefix(EPrefixError);
infoSink.info << "Function recursion detected"; infoSink.info << "Function recursion detected";
return false; return false;
case DetectCallDepth::kErrorMaxDepthExceeded:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function call stack too deep";
return false;
default: default:
UNREACHABLE(); UNREACHABLE();
return false;
} }
} }
...@@ -326,6 +338,28 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) ...@@ -326,6 +338,28 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
} }
} }
bool TCompiler::limitExpressionComplexity(TIntermNode* root)
{
TIntermTraverser traverser;
root->traverse(&traverser);
TDependencyGraph graph(root);
for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
iter != graph.endUserDefinedFunctionCalls();
++iter)
{
TGraphFunctionCall* samplerSymbol = *iter;
TDependencyGraphTraverser graphTraverser;
samplerSymbol->traverse(&graphTraverser);
}
if (traverser.getMaxDepth() > maxExpressionComplexity) {
infoSink.info << "Expression too complex.";
return false;
}
return true;
}
bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph) bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
{ {
RestrictFragmentShaderTiming restrictor(infoSink.info); RestrictFragmentShaderTiming restrictor(infoSink.info);
......
...@@ -4,21 +4,24 @@ ...@@ -4,21 +4,24 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#include "compiler/DetectRecursion.h" #include "compiler/DetectCallDepth.h"
#include "compiler/InfoSink.h"
DetectRecursion::FunctionNode::FunctionNode(const TString& fname) const int DetectCallDepth::FunctionNode::kInfiniteCallDepth;
DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
: name(fname), : name(fname),
visit(PreVisit) visit(PreVisit)
{ {
} }
const TString& DetectRecursion::FunctionNode::getName() const const TString& DetectCallDepth::FunctionNode::getName() const
{ {
return name; return name;
} }
void DetectRecursion::FunctionNode::addCallee( void DetectCallDepth::FunctionNode::addCallee(
DetectRecursion::FunctionNode* callee) DetectCallDepth::FunctionNode* callee)
{ {
for (size_t i = 0; i < callees.size(); ++i) { for (size_t i = 0; i < callees.size(); ++i) {
if (callees[i] == callee) if (callees[i] == callee)
...@@ -27,21 +30,31 @@ void DetectRecursion::FunctionNode::addCallee( ...@@ -27,21 +30,31 @@ void DetectRecursion::FunctionNode::addCallee(
callees.push_back(callee); callees.push_back(callee);
} }
bool DetectRecursion::FunctionNode::detectRecursion() int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
{ {
ASSERT(visit == PreVisit); ASSERT(visit == PreVisit);
ASSERT(detectCallDepth);
int maxDepth = depth;
visit = InVisit; visit = InVisit;
for (size_t i = 0; i < callees.size(); ++i) { for (size_t i = 0; i < callees.size(); ++i) {
switch (callees[i]->visit) { switch (callees[i]->visit) {
case InVisit: case InVisit:
// cycle detected, i.e., recursion detected. // cycle detected, i.e., recursion detected.
return true; return kInfiniteCallDepth;
case PostVisit: case PostVisit:
break; break;
case PreVisit: { case PreVisit: {
bool recursion = callees[i]->detectRecursion(); // Check before we recurse so we don't go too depth
if (recursion) if (detectCallDepth->checkExceedsMaxDepth(depth))
return true; return depth;
int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
// Check after we recurse so we can exit immediately and provide info.
if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
return callDepth;
}
maxDepth = std::max(callDepth, maxDepth);
break; break;
} }
default: default:
...@@ -50,21 +63,29 @@ bool DetectRecursion::FunctionNode::detectRecursion() ...@@ -50,21 +63,29 @@ bool DetectRecursion::FunctionNode::detectRecursion()
} }
} }
visit = PostVisit; visit = PostVisit;
return false; return maxDepth;
} }
DetectRecursion::DetectRecursion() void DetectCallDepth::FunctionNode::reset()
: currentFunction(NULL)
{ {
visit = PreVisit;
} }
DetectRecursion::~DetectRecursion() DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
: TIntermTraverser(true, false, true, false),
currentFunction(NULL),
infoSink(infoSink),
maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
{
}
DetectCallDepth::~DetectCallDepth()
{ {
for (size_t i = 0; i < functions.size(); ++i) for (size_t i = 0; i < functions.size(); ++i)
delete functions[i]; delete functions[i];
} }
bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node) bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
{ {
switch (node->getOp()) switch (node->getOp())
{ {
...@@ -81,19 +102,21 @@ bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -81,19 +102,21 @@ bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node)
currentFunction = new FunctionNode(node->getName()); currentFunction = new FunctionNode(node->getName());
functions.push_back(currentFunction); functions.push_back(currentFunction);
} }
} else if (visit == PostVisit) {
currentFunction = NULL;
} }
break; break;
} }
case EOpFunctionCall: { case EOpFunctionCall: {
// Function call. // Function call.
if (visit == PreVisit) { if (visit == PreVisit) {
ASSERT(currentFunction != NULL);
FunctionNode* func = findFunctionByName(node->getName()); FunctionNode* func = findFunctionByName(node->getName());
if (func == NULL) { if (func == NULL) {
func = new FunctionNode(node->getName()); func = new FunctionNode(node->getName());
functions.push_back(func); functions.push_back(func);
} }
currentFunction->addCallee(func); if (currentFunction)
currentFunction->addCallee(func);
} }
break; break;
} }
...@@ -103,17 +126,56 @@ bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -103,17 +126,56 @@ bool DetectRecursion::visitAggregate(Visit visit, TIntermAggregate* node)
return true; return true;
} }
DetectRecursion::ErrorCode DetectRecursion::detectRecursion() bool DetectCallDepth::checkExceedsMaxDepth(int depth)
{
return depth >= maxDepth;
}
void DetectCallDepth::resetFunctionNodes()
{
for (size_t i = 0; i < functions.size(); ++i) {
functions[i]->reset();
}
}
DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
{ {
FunctionNode* main = findFunctionByName("main("); currentFunction = NULL;
if (main == NULL) resetFunctionNodes();
return kErrorMissingMain;
if (main->detectRecursion()) int maxCallDepth = func->detectCallDepth(this, 1);
if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
return kErrorRecursion; return kErrorRecursion;
if (maxCallDepth >= maxDepth)
return kErrorMaxDepthExceeded;
return kErrorNone;
}
DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
{
if (maxDepth != FunctionNode::kInfiniteCallDepth) {
// Check all functions because the driver may fail on them
// TODO: Before detectingRecursion, strip unused functions.
for (size_t i = 0; i < functions.size(); ++i) {
ErrorCode error = detectCallDepthForFunction(functions[i]);
if (error != kErrorNone)
return error;
}
} else {
FunctionNode* main = findFunctionByName("main(");
if (main == NULL)
return kErrorMissingMain;
return detectCallDepthForFunction(main);
}
return kErrorNone; return kErrorNone;
} }
DetectRecursion::FunctionNode* DetectRecursion::findFunctionByName( DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
const TString& name) const TString& name)
{ {
for (size_t i = 0; i < functions.size(); ++i) { for (size_t i = 0; i < functions.size(); ++i) {
......
...@@ -9,28 +9,36 @@ ...@@ -9,28 +9,36 @@
#include "GLSLANG/ShaderLang.h" #include "GLSLANG/ShaderLang.h"
#include <limits.h>
#include "compiler/intermediate.h" #include "compiler/intermediate.h"
#include "compiler/VariableInfo.h" #include "compiler/VariableInfo.h"
class TInfoSink;
// Traverses intermediate tree to detect function recursion. // Traverses intermediate tree to detect function recursion.
class DetectRecursion : public TIntermTraverser { class DetectCallDepth : public TIntermTraverser {
public: public:
enum ErrorCode { enum ErrorCode {
kErrorMissingMain, kErrorMissingMain,
kErrorRecursion, kErrorRecursion,
kErrorMaxDepthExceeded,
kErrorNone kErrorNone
}; };
DetectRecursion(); DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth);
~DetectRecursion(); ~DetectCallDepth();
virtual bool visitAggregate(Visit, TIntermAggregate*); virtual bool visitAggregate(Visit, TIntermAggregate*);
ErrorCode detectRecursion(); bool checkExceedsMaxDepth(int depth);
ErrorCode detectCallDepth();
private: private:
class FunctionNode { class FunctionNode {
public: public:
static const int kInfiniteCallDepth = INT_MAX;
FunctionNode(const TString& fname); FunctionNode(const TString& fname);
const TString& getName() const; const TString& getName() const;
...@@ -38,8 +46,11 @@ private: ...@@ -38,8 +46,11 @@ private:
// If a function is already in the callee list, this becomes a no-op. // If a function is already in the callee list, this becomes a no-op.
void addCallee(FunctionNode* callee); void addCallee(FunctionNode* callee);
// Return true if recursive function calls are detected. // Returns kInifinityCallDepth if recursive function calls are detected.
bool detectRecursion(); int detectCallDepth(DetectCallDepth* detectCallDepth, int depth);
// Reset state.
void reset();
private: private:
// mangled function name is unique. // mangled function name is unique.
...@@ -51,10 +62,19 @@ private: ...@@ -51,10 +62,19 @@ private:
Visit visit; Visit visit;
}; };
ErrorCode detectCallDepthForFunction(FunctionNode* func);
FunctionNode* findFunctionByName(const TString& name); FunctionNode* findFunctionByName(const TString& name);
void resetFunctionNodes();
TInfoSink& getInfoSink() { return infoSink; }
TVector<FunctionNode*> functions; TVector<FunctionNode*> functions;
FunctionNode* currentFunction; FunctionNode* currentFunction;
TInfoSink& infoSink;
int maxDepth;
DetectCallDepth(const DetectCallDepth&);
void operator=(const DetectCallDepth&);
}; };
#endif // COMPILER_DETECT_RECURSION_H_ #endif // COMPILER_DETECT_RECURSION_H_
...@@ -81,8 +81,8 @@ protected: ...@@ -81,8 +81,8 @@ protected:
bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
// Clears the results from the previous compilation. // Clears the results from the previous compilation.
void clearResults(); void clearResults();
// Return true if function recursion is detected. // Return true if function recursion is detected or call depth exceeded.
bool detectRecursion(TIntermNode* root); bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth);
// Rewrites a shader's intermediate tree according to the CSS Shaders spec. // Rewrites a shader's intermediate tree according to the CSS Shaders spec.
void rewriteCSSShader(TIntermNode* root); void rewriteCSSShader(TIntermNode* root);
// Returns true if the given shader does not exceed the minimum // Returns true if the given shader does not exceed the minimum
...@@ -104,6 +104,8 @@ protected: ...@@ -104,6 +104,8 @@ protected:
// Returns true if the shader does not use sampler dependent values to affect control // Returns true if the shader does not use sampler dependent values to affect control
// flow or in operations whose time can depend on the input values. // flow or in operations whose time can depend on the input values.
bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph); bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
// Return true if the maximum expression complexity below the limit.
bool limitExpressionComplexity(TIntermNode* root);
// Get built-in extensions with default behavior. // Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const; const TExtensionBehavior& getExtensionBehavior() const;
...@@ -116,6 +118,8 @@ private: ...@@ -116,6 +118,8 @@ private:
ShShaderSpec shaderSpec; ShShaderSpec shaderSpec;
int maxUniformVectors; int maxUniformVectors;
int maxExpressionComplexity;
int maxCallStackDepth;
// Built-in symbol table for the given language, spec, and resources. // Built-in symbol table for the given language, spec, and resources.
// It is preserved from compile-to-compile. // It is preserved from compile-to-compile.
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "GLSLANG/ShaderLang.h" #include "GLSLANG/ShaderLang.h"
#include <algorithm>
#include "compiler/Common.h" #include "compiler/Common.h"
#include "compiler/Types.h" #include "compiler/Types.h"
#include "compiler/ConstantUnion.h" #include "compiler/ConstantUnion.h"
...@@ -542,7 +543,8 @@ public: ...@@ -542,7 +543,8 @@ public:
inVisit(inVisit), inVisit(inVisit),
postVisit(postVisit), postVisit(postVisit),
rightToLeft(rightToLeft), rightToLeft(rightToLeft),
depth(0) {} depth(0),
maxDepth(0) {}
virtual ~TIntermTraverser() {}; virtual ~TIntermTraverser() {};
virtual void visitSymbol(TIntermSymbol*) {} virtual void visitSymbol(TIntermSymbol*) {}
...@@ -554,7 +556,8 @@ public: ...@@ -554,7 +556,8 @@ public:
virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
void incrementDepth() {depth++;} int getMaxDepth() const {return maxDepth;}
void incrementDepth() {depth++; maxDepth = std::max(maxDepth, depth); }
void decrementDepth() {depth--;} void decrementDepth() {depth--;}
// Return the original name if hash function pointer is NULL; // Return the original name if hash function pointer is NULL;
...@@ -568,6 +571,7 @@ public: ...@@ -568,6 +571,7 @@ public:
protected: protected:
int depth; int depth;
int maxDepth;
}; };
#endif // __INTERMEDIATE_H #endif // __INTERMEDIATE_H
...@@ -141,7 +141,7 @@ ...@@ -141,7 +141,7 @@
<ClCompile Include="BuiltInFunctionEmulator.cpp" /> <ClCompile Include="BuiltInFunctionEmulator.cpp" />
<ClCompile Include="Compiler.cpp" /> <ClCompile Include="Compiler.cpp" />
<ClCompile Include="debug.cpp" /> <ClCompile Include="debug.cpp" />
<ClCompile Include="DetectRecursion.cpp" /> <ClCompile Include="DetectCallDepth.cpp" />
<ClCompile Include="Diagnostics.cpp" /> <ClCompile Include="Diagnostics.cpp" />
<ClCompile Include="DirectiveHandler.cpp" /> <ClCompile Include="DirectiveHandler.cpp" />
<ClCompile Include="ForLoopUnroll.cpp" /> <ClCompile Include="ForLoopUnroll.cpp" />
...@@ -231,7 +231,7 @@ ...@@ -231,7 +231,7 @@
<ClInclude Include="Common.h" /> <ClInclude Include="Common.h" />
<ClInclude Include="ConstantUnion.h" /> <ClInclude Include="ConstantUnion.h" />
<ClInclude Include="debug.h" /> <ClInclude Include="debug.h" />
<ClInclude Include="DetectRecursion.h" /> <ClInclude Include="DetectCallDepth.h" />
<ClInclude Include="Diagnostics.h" /> <ClInclude Include="Diagnostics.h" />
<ClInclude Include="DirectiveHandler.h" /> <ClInclude Include="DirectiveHandler.h" />
<ClInclude Include="ForLoopUnroll.h" /> <ClInclude Include="ForLoopUnroll.h" />
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
<ClCompile Include="debug.cpp"> <ClCompile Include="debug.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="DetectRecursion.cpp"> <ClCompile Include="DetectCallDepth.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Diagnostics.cpp"> <ClCompile Include="Diagnostics.cpp">
...@@ -151,7 +151,7 @@ ...@@ -151,7 +151,7 @@
<ClInclude Include="debug.h"> <ClInclude Include="debug.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="DetectRecursion.h"> <ClInclude Include="DetectCallDepth.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Diagnostics.h"> <ClInclude Include="Diagnostics.h">
......
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
'target_name': 'compiler_tests', 'target_name': 'compiler_tests',
'type': 'executable', 'type': 'executable',
'dependencies': [ 'dependencies': [
'../src/build_angle.gyp:translator_common', '../src/build_angle.gyp:translator_glsl',
'gtest', 'gtest',
'gmock', 'gmock',
], ],
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
], ],
'sources': [ 'sources': [
'../third_party/googlemock/src/gmock_main.cc', '../third_party/googlemock/src/gmock_main.cc',
'compiler_tests/ExpressionLimit_test.cpp',
'compiler_tests/VariablePacker_test.cpp', 'compiler_tests/VariablePacker_test.cpp',
], ],
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment