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/ParseHelper.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:
15 0 : 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 0 : matrixSize(0) {
27 0 : }
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 : int index;
42 : ConstantUnion *unionArray;
43 : TType type;
44 : TOperator constructorType;
45 : bool singleConstantParam;
46 : TInfoSink& infoSink;
47 : TSymbolTable& symbolTable;
48 : int size; // size of the constructor ( 4 for vec4)
49 : bool isMatrix;
50 : int 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 :
62 0 : void TConstTraverser::visitSymbol(TIntermSymbol* node)
63 : {
64 0 : infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
65 : return;
66 :
67 : }
68 :
69 0 : bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
70 : {
71 0 : TQualifier qualifier = node->getType().getQualifier();
72 :
73 0 : if (qualifier != EvqConst) {
74 0 : TString buf;
75 0 : buf.append("'constructor' : assigning non-constant to ");
76 0 : buf.append(type.getCompleteString());
77 0 : infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
78 0 : error = true;
79 0 : return false;
80 : }
81 :
82 0 : infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
83 :
84 0 : return false;
85 : }
86 :
87 0 : bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
88 : {
89 0 : TString buf;
90 0 : buf.append("'constructor' : assigning non-constant to ");
91 0 : buf.append(type.getCompleteString());
92 0 : infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
93 0 : error = true;
94 0 : return false;
95 : }
96 :
97 0 : bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
98 : {
99 0 : if (!node->isConstructor() && node->getOp() != EOpComma) {
100 0 : TString buf;
101 0 : buf.append("'constructor' : assigning non-constant to ");
102 0 : buf.append(type.getCompleteString());
103 0 : infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
104 0 : error = true;
105 0 : return false;
106 : }
107 :
108 0 : if (node->getSequence().size() == 0) {
109 0 : error = true;
110 0 : return false;
111 : }
112 :
113 0 : bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
114 0 : if (flag)
115 : {
116 0 : singleConstantParam = true;
117 0 : constructorType = node->getOp();
118 0 : size = node->getType().getObjectSize();
119 :
120 0 : if (node->getType().isMatrix()) {
121 0 : isMatrix = true;
122 0 : matrixSize = node->getType().getNominalSize();
123 : }
124 : }
125 :
126 0 : for (TIntermSequence::iterator p = node->getSequence().begin();
127 0 : p != node->getSequence().end(); p++) {
128 :
129 0 : if (node->getOp() == EOpComma)
130 0 : index = 0;
131 :
132 0 : (*p)->traverse(this);
133 : }
134 0 : if (flag)
135 : {
136 0 : singleConstantParam = false;
137 0 : constructorType = EOpNull;
138 0 : size = 0;
139 0 : isMatrix = false;
140 0 : matrixSize = 0;
141 : }
142 0 : return false;
143 : }
144 :
145 0 : bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
146 : {
147 0 : infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
148 0 : error = true;
149 0 : return false;
150 : }
151 :
152 0 : void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
153 : {
154 0 : ConstantUnion* leftUnionArray = unionArray;
155 0 : int instanceSize = type.getObjectSize();
156 :
157 0 : if (index >= instanceSize)
158 0 : return;
159 :
160 0 : if (!singleConstantParam) {
161 0 : int size = node->getType().getObjectSize();
162 :
163 0 : ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
164 0 : for (int i=0; i < size; i++) {
165 0 : if (index >= instanceSize)
166 0 : return;
167 0 : leftUnionArray[index] = rightUnionArray[i];
168 :
169 0 : (index)++;
170 : }
171 : } else {
172 0 : int totalSize = index + size;
173 0 : ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
174 0 : if (!isMatrix) {
175 0 : int count = 0;
176 0 : for (int i = index; i < totalSize; i++) {
177 0 : if (i >= instanceSize)
178 0 : return;
179 :
180 0 : leftUnionArray[i] = rightUnionArray[count];
181 :
182 0 : (index)++;
183 :
184 0 : if (node->getType().getObjectSize() > 1)
185 0 : count++;
186 : }
187 : } else { // for matrix constructors
188 0 : int count = 0;
189 0 : int element = index;
190 0 : for (int i = index; i < totalSize; i++) {
191 0 : if (i >= instanceSize)
192 0 : return;
193 0 : if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
194 0 : leftUnionArray[i] = rightUnionArray[count];
195 : else
196 0 : leftUnionArray[i].setFConst(0.0f);
197 :
198 0 : (index)++;
199 :
200 0 : if (node->getType().getObjectSize() > 1)
201 0 : count++;
202 : }
203 : }
204 : }
205 : }
206 :
207 0 : bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
208 : {
209 0 : infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
210 0 : error = true;
211 0 : return false;
212 : }
213 :
214 0 : bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
215 : {
216 0 : infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
217 0 : error = true;
218 0 : return false;
219 : }
220 :
221 : //
222 : // This function is the one to call externally to start the traversal.
223 : // Individual functions can be initialized to 0 to skip processing of that
224 : // type of node. It's children will still be processed.
225 : //
226 0 : bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
227 : {
228 0 : if (root == 0)
229 0 : return false;
230 :
231 0 : TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
232 :
233 0 : root->traverse(&it);
234 0 : if (it.error)
235 0 : return true;
236 : else
237 0 : return false;
238 : }
|