blob: 10a3e517e273d1a892af84168b6e699e885c91fe [file] [log] [blame]
Olli Etuahob0c645e2015-05-12 14:25:36 +03001//
2// Copyright (c) 2002-2015 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/ParseContext.h"
10
Jamie Madill45bcc782016-11-07 13:58:48 -050011namespace sh
12{
13
Olli Etuahob0c645e2015-05-12 14:25:36 +030014namespace
15{
16
17class ValidateGlobalInitializerTraverser : public TIntermTraverser
18{
19 public:
20 ValidateGlobalInitializerTraverser(const TParseContext *context);
21
22 void visitSymbol(TIntermSymbol *node) override;
Olli Etuahoce39f6f2015-07-06 15:25:19 +030023 bool visitAggregate(Visit visit, TIntermAggregate *node) override;
Olli Etuaho846fe052015-07-07 17:41:21 +030024 bool visitBinary(Visit visit, TIntermBinary *node) override;
25 bool visitUnary(Visit visit, TIntermUnary *node) override;
Olli Etuahob0c645e2015-05-12 14:25:36 +030026
27 bool isValid() const { return mIsValid; }
28 bool issueWarning() const { return mIssueWarning; }
29
30 private:
31 const TParseContext *mContext;
32 bool mIsValid;
33 bool mIssueWarning;
34};
35
36void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
37{
Jamie Madilld7b1ab52016-12-12 14:42:19 -050038 const TSymbol *sym =
39 mContext->symbolTable.find(node->getSymbol(), mContext->getShaderVersion());
Olli Etuahob0c645e2015-05-12 14:25:36 +030040 if (sym->isVariable())
41 {
42 // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3):
43 // Global initializers must be constant expressions.
44 const TVariable *var = static_cast<const TVariable *>(sym);
45 switch (var->getType().getQualifier())
46 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -050047 case EvqConst:
48 break;
49 case EvqGlobal:
50 case EvqTemporary:
51 case EvqUniform:
52 // We allow these cases to be compatible with legacy ESSL 1.00 content.
53 // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal
54 // with.
55 if (mContext->getShaderVersion() >= 300)
56 {
57 mIsValid = false;
58 }
59 else
60 {
61 mIssueWarning = true;
62 }
63 break;
64 default:
Olli Etuahob0c645e2015-05-12 14:25:36 +030065 mIsValid = false;
Olli Etuahob0c645e2015-05-12 14:25:36 +030066 }
67 }
68}
69
Olli Etuahoce39f6f2015-07-06 15:25:19 +030070bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
71{
Jamie Madilld7b1ab52016-12-12 14:42:19 -050072 // Disallow calls to user-defined functions and texture lookup functions in global variable
73 // initializers.
74 // This is done simply by disabling all function calls - built-in math functions don't use
Olli Etuaho1ecd14b2017-01-26 13:54:15 -080075 // the function call ops.
76 if (node->isFunctionCall())
Olli Etuahoce39f6f2015-07-06 15:25:19 +030077 {
78 mIsValid = false;
79 }
80 return true;
81}
82
Olli Etuaho846fe052015-07-07 17:41:21 +030083bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node)
84{
85 if (node->isAssignment())
86 {
87 mIsValid = false;
88 }
89 return true;
90}
91
92bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node)
93{
94 if (node->isAssignment())
95 {
96 mIsValid = false;
97 }
98 return true;
99}
100
Olli Etuahob0c645e2015-05-12 14:25:36 +0300101ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(const TParseContext *context)
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500102 : TIntermTraverser(true, false, false), mContext(context), mIsValid(true), mIssueWarning(false)
Olli Etuahob0c645e2015-05-12 14:25:36 +0300103{
104}
105
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500106} // namespace
Olli Etuahob0c645e2015-05-12 14:25:36 +0300107
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500108bool ValidateGlobalInitializer(TIntermTyped *initializer,
109 const TParseContext *context,
110 bool *warning)
Olli Etuahob0c645e2015-05-12 14:25:36 +0300111{
112 ValidateGlobalInitializerTraverser validate(context);
113 initializer->traverse(&validate);
114 ASSERT(warning != nullptr);
115 *warning = validate.issueWarning();
116 return validate.isValid();
117}
118
Jamie Madill45bcc782016-11-07 13:58:48 -0500119} // namespace sh