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