blob: 6d79bbfeb6555fe474b6b09c50285274249bb5f9 [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
Olli Etuahoc26214d2018-03-16 10:43:11 +02009#include "compiler/translator/tree_util/IntermTraverse.h"
Olli Etuahob0c645e2015-05-12 14:25:36 +030010
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:
Olli Etuahoa2d98142017-12-15 14:18:55 +020020 ValidateGlobalInitializerTraverser(int shaderVersion);
Olli Etuahob0c645e2015-05-12 14:25:36 +030021
22 void visitSymbol(TIntermSymbol *node) override;
Olli Etuahoa2d98142017-12-15 14:18:55 +020023 void visitConstantUnion(TIntermConstantUnion *node) override;
Olli Etuahoce39f6f2015-07-06 15:25:19 +030024 bool visitAggregate(Visit visit, TIntermAggregate *node) override;
Olli Etuaho846fe052015-07-07 17:41:21 +030025 bool visitBinary(Visit visit, TIntermBinary *node) override;
26 bool visitUnary(Visit visit, TIntermUnary *node) override;
Olli Etuahob0c645e2015-05-12 14:25:36 +030027
28 bool isValid() const { return mIsValid; }
29 bool issueWarning() const { return mIssueWarning; }
30
31 private:
Olli Etuahoa2d98142017-12-15 14:18:55 +020032 int mShaderVersion;
Olli Etuahob0c645e2015-05-12 14:25:36 +030033 bool mIsValid;
34 bool mIssueWarning;
35};
36
37void ValidateGlobalInitializerTraverser::visitSymbol(TIntermSymbol *node)
38{
Olli Etuahoa2d98142017-12-15 14:18:55 +020039 // ESSL 1.00 section 4.3 (or ESSL 3.00 section 4.3):
40 // Global initializers must be constant expressions.
41 switch (node->getType().getQualifier())
Olli Etuahob0c645e2015-05-12 14:25:36 +030042 {
Olli Etuahoa2d98142017-12-15 14:18:55 +020043 case EvqConst:
44 break;
45 case EvqGlobal:
46 case EvqTemporary:
47 case EvqUniform:
48 // We allow these cases to be compatible with legacy ESSL 1.00 content.
49 // Implement stricter rules for ESSL 3.00 since there's no legacy content to deal
50 // with.
51 if (mShaderVersion >= 300)
52 {
Olli Etuahob0c645e2015-05-12 14:25:36 +030053 mIsValid = false;
Olli Etuahoa2d98142017-12-15 14:18:55 +020054 }
55 else
56 {
57 mIssueWarning = true;
58 }
59 break;
60 default:
61 mIsValid = false;
62 }
63}
64
65void ValidateGlobalInitializerTraverser::visitConstantUnion(TIntermConstantUnion *node)
66{
67 // Constant unions that are not constant expressions may result from folding a ternary
68 // expression.
69 switch (node->getType().getQualifier())
70 {
71 case EvqConst:
72 break;
73 case EvqTemporary:
74 if (mShaderVersion >= 300)
75 {
76 mIsValid = false;
77 }
78 else
79 {
80 mIssueWarning = true;
81 }
82 break;
83 default:
84 UNREACHABLE();
Olli Etuahob0c645e2015-05-12 14:25:36 +030085 }
86}
87
Olli Etuahoce39f6f2015-07-06 15:25:19 +030088bool ValidateGlobalInitializerTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
89{
Jamie Madilld7b1ab52016-12-12 14:42:19 -050090 // Disallow calls to user-defined functions and texture lookup functions in global variable
91 // initializers.
92 // This is done simply by disabling all function calls - built-in math functions don't use
Olli Etuaho1ecd14b2017-01-26 13:54:15 -080093 // the function call ops.
94 if (node->isFunctionCall())
Olli Etuahoce39f6f2015-07-06 15:25:19 +030095 {
96 mIsValid = false;
97 }
98 return true;
99}
100
Olli Etuaho846fe052015-07-07 17:41:21 +0300101bool ValidateGlobalInitializerTraverser::visitBinary(Visit visit, TIntermBinary *node)
102{
103 if (node->isAssignment())
104 {
105 mIsValid = false;
106 }
107 return true;
108}
109
110bool ValidateGlobalInitializerTraverser::visitUnary(Visit visit, TIntermUnary *node)
111{
112 if (node->isAssignment())
113 {
114 mIsValid = false;
115 }
116 return true;
117}
118
Olli Etuahoa2d98142017-12-15 14:18:55 +0200119ValidateGlobalInitializerTraverser::ValidateGlobalInitializerTraverser(int shaderVersion)
120 : TIntermTraverser(true, false, false),
121 mShaderVersion(shaderVersion),
122 mIsValid(true),
123 mIssueWarning(false)
Olli Etuahob0c645e2015-05-12 14:25:36 +0300124{
125}
126
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500127} // namespace
Olli Etuahob0c645e2015-05-12 14:25:36 +0300128
Olli Etuahoa2d98142017-12-15 14:18:55 +0200129bool ValidateGlobalInitializer(TIntermTyped *initializer, int shaderVersion, bool *warning)
Olli Etuahob0c645e2015-05-12 14:25:36 +0300130{
Olli Etuahoa2d98142017-12-15 14:18:55 +0200131 ValidateGlobalInitializerTraverser validate(shaderVersion);
Olli Etuahob0c645e2015-05-12 14:25:36 +0300132 initializer->traverse(&validate);
133 ASSERT(warning != nullptr);
134 *warning = validate.issueWarning();
135 return validate.isValid();
136}
137
Jamie Madill45bcc782016-11-07 13:58:48 -0500138} // namespace sh