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