// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "ValidateGlobalInitializer.h" #include "ParseHelper.h" namespace { class ValidateGlobalInitializerTraverser : public TIntermTraverser { public: ValidateGlobalInitializerTraverser(const TParseContext *context); void visitSymbol(TIntermSymbol *node) override; bool isValid() const { return mIsValid; } bool issueWarning() const { return mIssueWarning; } private: const TParseContext *mContext; bool mIsValid; bool mIssueWarning; }; void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node) { const TSymbol *sym = mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion()); if (sym->isVariable()) { // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3): // Global initializers must be constant expressions. const TVariable *var = static_cast(sym); switch (var->getType().getQualifier()) { case EvqConstExpr: break; case EvqGlobal: case EvqTemporary: case EvqUniform: // We allow these cases to be compatible with legacy ESSL 1.00 content. // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal with. if (mContext->getShaderVersion() >= 300) { mIsValid = false; } else { mIssueWarning = true; } break; default: mIsValid = false; } } } ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context) : TIntermTraverser(true, false, false), mContext(context), mIsValid(true), mIssueWarning(false) { } } // namespace bool ValidateGlobalInitializer(TIntermTyped *initializer, const TParseContext *context, bool *warning) { ValidateGlobalInitializerTraverser validate(context); initializer->traverse(&validate); ASSERT(warning != nullptr); *warning = validate.issueWarning(); return validate.isValid(); }