ValidateGlobalInitializer.cpp (4839B)
1 // 2 // Copyright 2002 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 7 #include "compiler/translator/ValidateGlobalInitializer.h" 8 9 #include "compiler/translator/tree_util/IntermTraverse.h" 10 11 namespace sh 12 { 13 14 namespace 15 { 16 17 const int kMaxAllowedTraversalDepth = 256; 18 19 class ValidateGlobalInitializerTraverser : public TIntermTraverser 20 { 21 public: 22 ValidateGlobalInitializerTraverser(int shaderVersion, 23 bool isWebGL, 24 bool hasExtNonConstGlobalInitializers); 25 26 void visitSymbol(TIntermSymbol *node) override; 27 void visitConstantUnion(TIntermConstantUnion *node) override; 28 bool visitAggregate(Visit visit, TIntermAggregate *node) override; 29 bool visitBinary(Visit visit, TIntermBinary *node) override; 30 bool visitUnary(Visit visit, TIntermUnary *node) override; 31 32 bool isValid() const { return mIsValid && mMaxDepth < mMaxAllowedDepth; } 33 bool issueWarning() const { return mIssueWarning; } 34 35 private: 36 ANGLE_INLINE void onNonConstInitializerVisit(bool accept) 37 { 38 if (accept) 39 { 40 if (!mExtNonConstGlobalInitializers) 41 { 42 mIssueWarning = true; 43 } 44 } 45 else 46 { 47 mIsValid = false; 48 } 49 } 50 51 int mShaderVersion; 52 bool mIsWebGL; 53 bool mExtNonConstGlobalInitializers; 54 bool mIsValid; 55 bool mIssueWarning; 56 }; 57 58 void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) 59 { 60 // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): 61 // Global initializers must be constant expressions. 62 switch (node->getType().getQualifier()) 63 { 64 case EvqConst: 65 break; 66 case EvqGlobal: 67 case EvqTemporary: 68 case EvqUniform: 69 // We allow these cases to be compatible with legacy ESSL 1.00 content. 70 // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal 71 // with. 72 onNonConstInitializerVisit(mExtNonConstGlobalInitializers || 73 ((mShaderVersion < 300) && mIsWebGL)); 74 break; 75 default: 76 mIsValid = false; 77 } 78 } 79 80 void ValidateGlobalInitializerTraverser::visitConstantUnion(TIntermConstantUnion *node) 81 { 82 // Constant unions that are not constant expressions may result from folding a ternary 83 // expression. 84 switch (node->getType().getQualifier()) 85 { 86 case EvqConst: 87 break; 88 case EvqTemporary: 89 onNonConstInitializerVisit(mExtNonConstGlobalInitializers || 90 ((mShaderVersion < 300) && mIsWebGL)); 91 break; 92 default: 93 UNREACHABLE(); 94 } 95 } 96 97 bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node) 98 { 99 // Disallow calls to user-defined functions and texture lookup functions in global variable 100 // initializers. For simplicity, all non-math built-in calls are disallowed. 101 if (node->isFunctionCall() || 102 (BuiltInGroup::IsBuiltIn(node->getOp()) && !BuiltInGroup::IsMath(node->getOp()))) 103 { 104 onNonConstInitializerVisit(mExtNonConstGlobalInitializers); 105 } 106 return true; 107 } 108 109 bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node) 110 { 111 if (node->isAssignment()) 112 { 113 onNonConstInitializerVisit(mExtNonConstGlobalInitializers); 114 } 115 return true; 116 } 117 118 bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node) 119 { 120 if (node->isAssignment()) 121 { 122 onNonConstInitializerVisit(mExtNonConstGlobalInitializers); 123 } 124 return true; 125 } 126 127 ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser( 128 int shaderVersion, 129 bool isWebGL, 130 bool hasExtNonConstGlobalInitializers) 131 : TIntermTraverser(true, false, false, nullptr), 132 mShaderVersion(shaderVersion), 133 mIsWebGL(isWebGL), 134 mExtNonConstGlobalInitializers(hasExtNonConstGlobalInitializers), 135 mIsValid(true), 136 mIssueWarning(false) 137 { 138 setMaxAllowedDepth(kMaxAllowedTraversalDepth); 139 } 140 141 } // namespace 142 143 bool ValidateGlobalInitializer(TIntermTyped *initializer, 144 int shaderVersion, 145 bool isWebGL, 146 bool hasExtNonConstGlobalInitializers, 147 bool *warning) 148 { 149 ValidateGlobalInitializerTraverser validate(shaderVersion, isWebGL, 150 hasExtNonConstGlobalInitializers); 151 initializer->traverse(&validate); 152 ASSERT(warning != nullptr); 153 *warning = validate.issueWarning(); 154 return validate.isValid(); 155 } 156 157 } // namespace sh