• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2002-2013 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/ParseContext.h"
8 
9 //
10 // Use this class to carry along data from node to node in
11 // the traversal
12 //
13 class TConstTraverser : public TIntermTraverser {
14 public:
TConstTraverser(ConstantUnion * cUnion,bool singleConstParam,TOperator constructType,TInfoSink & sink,TType & t)15     TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t)
16         : error(false),
17           index(0),
18           unionArray(cUnion),
19           type(t),
20           constructorType(constructType),
21           singleConstantParam(singleConstParam),
22           infoSink(sink),
23           size(0),
24           isDiagonalMatrixInit(false),
25           matrixCols(0),
26           matrixRows(0) {
27     }
28 
29     bool error;
30 
31 protected:
32     void visitSymbol(TIntermSymbol*);
33     void visitConstantUnion(TIntermConstantUnion*);
34     bool visitBinary(Visit visit, TIntermBinary*);
35     bool visitUnary(Visit visit, TIntermUnary*);
36     bool visitSelection(Visit visit, TIntermSelection*);
37     bool visitAggregate(Visit visit, TIntermAggregate*);
38     bool visitLoop(Visit visit, TIntermLoop*);
39     bool visitBranch(Visit visit, TIntermBranch*);
40 
41     size_t index;
42     ConstantUnion *unionArray;
43     TType type;
44     TOperator constructorType;
45     bool singleConstantParam;
46     TInfoSink& infoSink;
47     size_t size; // size of the constructor ( 4 for vec4)
48     bool isDiagonalMatrixInit;
49     int matrixCols; // columns of the matrix
50     int matrixRows; // rows of the matrix
51 };
52 
53 //
54 // The rest of the file are the traversal functions.  The last one
55 // is the one that starts the traversal.
56 //
57 // Return true from interior nodes to have the external traversal
58 // continue on to children.  If you process children yourself,
59 // return false.
60 //
61 
visitSymbol(TIntermSymbol * node)62 void TConstTraverser::visitSymbol(TIntermSymbol* node)
63 {
64     infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor");
65     return;
66 
67 }
68 
visitBinary(Visit visit,TIntermBinary * node)69 bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
70 {
71     TQualifier qualifier = node->getType().getQualifier();
72 
73     if (qualifier != EvqConst) {
74         TString buf;
75         buf.append("'constructor' : assigning non-constant to ");
76         buf.append(type.getCompleteString());
77         infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
78         error = true;
79         return false;
80     }
81 
82    infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor");
83 
84     return false;
85 }
86 
visitUnary(Visit visit,TIntermUnary * node)87 bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
88 {
89     TString buf;
90     buf.append("'constructor' : assigning non-constant to ");
91     buf.append(type.getCompleteString());
92     infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
93     error = true;
94     return false;
95 }
96 
visitAggregate(Visit visit,TIntermAggregate * node)97 bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
98 {
99     if (!node->isConstructor() && node->getOp() != EOpComma) {
100         TString buf;
101         buf.append("'constructor' : assigning non-constant to ");
102         buf.append(type.getCompleteString());
103         infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
104         error = true;
105         return false;
106     }
107 
108     if (node->getSequence().size() == 0) {
109         error = true;
110         return false;
111     }
112 
113     bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
114     if (flag)
115     {
116         singleConstantParam = true;
117         constructorType = node->getOp();
118         size = node->getType().getObjectSize();
119 
120         if (node->getType().isMatrix()) {
121             isDiagonalMatrixInit = true;
122             matrixCols = node->getType().getCols();
123             matrixRows = node->getType().getRows();
124         }
125     }
126 
127     for (TIntermSequence::iterator p = node->getSequence().begin();
128                                    p != node->getSequence().end(); p++) {
129 
130         if (node->getOp() == EOpComma)
131             index = 0;
132 
133         (*p)->traverse(this);
134     }
135     if (flag)
136     {
137         singleConstantParam = false;
138         constructorType = EOpNull;
139         size = 0;
140         isDiagonalMatrixInit = false;
141         matrixCols = 0;
142         matrixRows = 0;
143     }
144     return false;
145 }
146 
visitSelection(Visit visit,TIntermSelection * node)147 bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
148 {
149     infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
150     error = true;
151     return false;
152 }
153 
visitConstantUnion(TIntermConstantUnion * node)154 void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
155 {
156     if (!node->getUnionArrayPointer())
157     {
158         // The constant was not initialized, this should already have been logged
159         assert(infoSink.info.size() != 0);
160         return;
161     }
162 
163     ConstantUnion* leftUnionArray = unionArray;
164     size_t instanceSize = type.getObjectSize();
165 
166     if (index >= instanceSize)
167         return;
168 
169     if (!singleConstantParam) {
170         size_t objectSize = node->getType().getObjectSize();
171 
172         ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
173         for (size_t i=0; i < objectSize; i++) {
174             if (index >= instanceSize)
175                 return;
176             leftUnionArray[index] = rightUnionArray[i];
177 
178             (index)++;
179         }
180     } else {
181         size_t totalSize = index + size;
182         ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
183         if (!isDiagonalMatrixInit) {
184             int count = 0;
185             for (size_t i = index; i < totalSize; i++) {
186                 if (i >= instanceSize)
187                     return;
188 
189                 leftUnionArray[i] = rightUnionArray[count];
190 
191                 (index)++;
192 
193                 if (node->getType().getObjectSize() > 1)
194                     count++;
195             }
196         }
197         else
198         {
199             // for matrix diagonal constructors from a single scalar
200             for (int i = 0, col = 0; col < matrixCols; col++)
201             {
202                 for (int row = 0; row < matrixRows; row++, i++)
203                 {
204                     if (col == row)
205                     {
206                         leftUnionArray[i] = rightUnionArray[0];
207                     }
208                     else
209                     {
210                         leftUnionArray[i].setFConst(0.0f);
211                     }
212 
213                     (index)++;
214                 }
215             }
216         }
217     }
218 }
219 
visitLoop(Visit visit,TIntermLoop * node)220 bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
221 {
222     infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
223     error = true;
224     return false;
225 }
226 
visitBranch(Visit visit,TIntermBranch * node)227 bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
228 {
229     infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
230     error = true;
231     return false;
232 }
233 
234 //
235 // This function is the one to call externally to start the traversal.
236 // Individual functions can be initialized to 0 to skip processing of that
237 // type of node.  It's children will still be processed.
238 //
parseConstTree(const TSourceLoc & line,TIntermNode * root,ConstantUnion * unionArray,TOperator constructorType,TType t,bool singleConstantParam)239 bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam)
240 {
241     if (root == 0)
242         return false;
243 
244     TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t);
245 
246     root->traverse(&it);
247     if (it.error)
248         return true;
249     else
250         return false;
251 }
252