• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2002-2010 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/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,TSymbolTable & symTable,TType & t)15     TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t)
16         : error(false),
17           index(0),
18           unionArray(cUnion),
19           type(t),
20           constructorType(constructType),
21           singleConstantParam(singleConstParam),
22           infoSink(sink),
23           symbolTable(symTable),
24           size(0),
25           isMatrix(false),
26           matrixSize(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     TSymbolTable& symbolTable;
48     size_t size; // size of the constructor ( 4 for vec4)
49     bool isMatrix;
50     size_t matrixSize; // dimension of the matrix (nominal size and not the instance size)
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             isMatrix = true;
122             matrixSize = node->getType().getNominalSize();
123         }
124     }
125 
126     for (TIntermSequence::iterator p = node->getSequence().begin();
127                                    p != node->getSequence().end(); p++) {
128 
129         if (node->getOp() == EOpComma)
130             index = 0;
131 
132         (*p)->traverse(this);
133     }
134     if (flag)
135     {
136         singleConstantParam = false;
137         constructorType = EOpNull;
138         size = 0;
139         isMatrix = false;
140         matrixSize = 0;
141     }
142     return false;
143 }
144 
visitSelection(Visit visit,TIntermSelection * node)145 bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
146 {
147     infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
148     error = true;
149     return false;
150 }
151 
visitConstantUnion(TIntermConstantUnion * node)152 void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
153 {
154     if (!node->getUnionArrayPointer())
155     {
156         // The constant was not initialized, this should already have been logged
157         assert(infoSink.info.size() != 0);
158         return;
159     }
160 
161     ConstantUnion* leftUnionArray = unionArray;
162     size_t instanceSize = type.getObjectSize();
163 
164     if (index >= instanceSize)
165         return;
166 
167     if (!singleConstantParam) {
168         size_t size = node->getType().getObjectSize();
169 
170         ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
171         for (size_t i = 0; i < size; i++) {
172             if (index >= instanceSize)
173                 return;
174             leftUnionArray[index] = rightUnionArray[i];
175 
176             (index)++;
177         }
178     } else {
179         size_t totalSize = index + size;
180         ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
181         if (!isMatrix) {
182             size_t count = 0;
183             for (size_t i = index; i < totalSize; i++) {
184                 if (i >= instanceSize)
185                     return;
186 
187                 leftUnionArray[i] = rightUnionArray[count];
188 
189                 (index)++;
190 
191                 if (node->getType().getObjectSize() > 1)
192                     count++;
193             }
194         } else {  // for matrix constructors
195             size_t count = 0;
196             size_t element = index;
197             for (size_t i = index; i < totalSize; i++) {
198                 if (i >= instanceSize)
199                     return;
200                 if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
201                     leftUnionArray[i] = rightUnionArray[count];
202                 else
203                     leftUnionArray[i].setFConst(0.0f);
204 
205                 (index)++;
206 
207                 if (node->getType().getObjectSize() > 1)
208                     count++;
209             }
210         }
211     }
212 }
213 
visitLoop(Visit visit,TIntermLoop * node)214 bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
215 {
216     infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
217     error = true;
218     return false;
219 }
220 
visitBranch(Visit visit,TIntermBranch * node)221 bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
222 {
223     infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
224     error = true;
225     return false;
226 }
227 
228 //
229 // This function is the one to call externally to start the traversal.
230 // Individual functions can be initialized to 0 to skip processing of that
231 // type of node.  It's children will still be processed.
232 //
parseConstTree(const TSourceLoc & line,TIntermNode * root,ConstantUnion * unionArray,TOperator constructorType,TSymbolTable & symbolTable,TType t,bool singleConstantParam)233 bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
234 {
235     if (root == 0)
236         return false;
237 
238     TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
239 
240     root->traverse(&it);
241     if (it.error)
242         return true;
243     else
244         return false;
245 }
246