1// Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15#include "ValidateGlobalInitializer.h" 16 17#include "ParseHelper.h" 18 19namespace 20{ 21 22class ValidateGlobalInitializerTraverser : public TIntermTraverser 23{ 24public: 25 ValidateGlobalInitializerTraverser(const TParseContext *context); 26 27 void visitSymbol(TIntermSymbol *node) override; 28 29 bool isValid() const { return mIsValid; } 30 bool issueWarning() const { return mIssueWarning; } 31 32private: 33 const TParseContext *mContext; 34 bool mIsValid; 35 bool mIssueWarning; 36}; 37 38void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) 39{ 40 const TSymbol *sym = mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion()); 41 if (sym->isVariable()) 42 { 43 // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): 44 // Global initializers must be constant expressions. 45 const TVariable *var = static_cast<const TVariable *>(sym); 46 switch (var->getType().getQualifier()) 47 { 48 case EvqConstExpr: 49 break; 50 case EvqGlobal: 51 case EvqTemporary: 52 case EvqUniform: 53 // We allow these cases to be compatible with legacy ESSL 1.00 content. 54 // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal with. 55 if (mContext->getShaderVersion() >= 300) 56 { 57 mIsValid = false; 58 } 59 else 60 { 61 mIssueWarning = true; 62 } 63 break; 64 default: 65 mIsValid = false; 66 } 67 } 68} 69 70ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context) 71 : TIntermTraverser(true, false, false), 72 mContext(context), 73 mIsValid(true), 74 mIssueWarning(false) 75{ 76} 77 78} // namespace 79 80bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning) 81{ 82 ValidateGlobalInitializerTraverser validate(context); 83 initializer->traverse(&validate); 84 ASSERT(warning != nullptr); 85 *warning = validate.issueWarning(); 86 return validate.isValid(); 87} 88 89