blob: 77d996f26bfc9eaaae8b2aac9ed629eb1b955784 [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:
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000015 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),
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +000025 isDiagonalMatrixInit(false),
26 matrixCols(0),
27 matrixRows(0) {
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000028 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000030 bool error;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031
32protected:
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000033 void visitSymbol(TIntermSymbol*);
34 void visitConstantUnion(TIntermConstantUnion*);
35 bool visitBinary(Visit visit, TIntermBinary*);
36 bool visitUnary(Visit visit, TIntermUnary*);
37 bool visitSelection(Visit visit, TIntermSelection*);
38 bool visitAggregate(Visit visit, TIntermAggregate*);
39 bool visitLoop(Visit visit, TIntermLoop*);
40 bool visitBranch(Visit visit, TIntermBranch*);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000041
42 int index;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +000043 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000044 TType type;
45 TOperator constructorType;
46 bool singleConstantParam;
47 TInfoSink& infoSink;
48 TSymbolTable& symbolTable;
49 int size; // size of the constructor ( 4 for vec4)
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +000050 bool isDiagonalMatrixInit;
51 int matrixCols; // columns of the matrix
52 int matrixRows; // rows of the matrix
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000053};
54
55//
56// The rest of the file are the traversal functions. The last one
57// is the one that starts the traversal.
58//
59// Return true from interior nodes to have the external traversal
60// continue on to children. If you process children yourself,
61// return false.
62//
63
64void TConstTraverser::visitSymbol(TIntermSymbol* node)
65{
66 infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
67 return;
68
69}
70
71bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
72{
73 TQualifier qualifier = node->getType().getQualifier();
74
75 if (qualifier != EvqConst) {
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000076 TString buf;
77 buf.append("'constructor' : assigning non-constant to ");
78 buf.append(type.getCompleteString());
79 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080 error = true;
81 return false;
82 }
83
84 infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
85
86 return false;
87}
88
89bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
90{
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000091 TString buf;
92 buf.append("'constructor' : assigning non-constant to ");
93 buf.append(type.getCompleteString());
94 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095 error = true;
96 return false;
97}
98
99bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
100{
101 if (!node->isConstructor() && node->getOp() != EOpComma) {
alokp@chromium.org4e4facd2010-06-02 15:21:22 +0000102 TString buf;
103 buf.append("'constructor' : assigning non-constant to ");
104 buf.append(type.getCompleteString());
105 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106 error = true;
107 return false;
108 }
109
110 if (node->getSequence().size() == 0) {
111 error = true;
112 return false;
113 }
114
115 bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
116 if (flag)
117 {
118 singleConstantParam = true;
119 constructorType = node->getOp();
120 size = node->getType().getObjectSize();
121
122 if (node->getType().isMatrix()) {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000123 isDiagonalMatrixInit = true;
124 matrixCols = node->getType().getCols();
125 matrixRows = node->getType().getRows();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126 }
127 }
128
129 for (TIntermSequence::iterator p = node->getSequence().begin();
130 p != node->getSequence().end(); p++) {
131
132 if (node->getOp() == EOpComma)
133 index = 0;
134
135 (*p)->traverse(this);
136 }
137 if (flag)
138 {
139 singleConstantParam = false;
140 constructorType = EOpNull;
141 size = 0;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000142 isDiagonalMatrixInit = false;
143 matrixCols = 0;
144 matrixRows = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145 }
146 return false;
147}
148
149bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
150{
151 infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
152 error = true;
153 return false;
154}
155
156void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
157{
shannon.woods%transgaming.com@gtempaccount.com6df256c2013-04-13 03:29:46 +0000158 if (!node->getUnionArrayPointer())
159 {
160 // The constant was not initialized, this should already have been logged
161 assert(infoSink.info.size() != 0);
162 return;
163 }
164
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000165 ConstantUnion* leftUnionArray = unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166 int instanceSize = type.getObjectSize();
167
168 if (index >= instanceSize)
169 return;
170
171 if (!singleConstantParam) {
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000172 int objectSize = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000174 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000175 for (int i=0; i < objectSize; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176 if (index >= instanceSize)
177 return;
178 leftUnionArray[index] = rightUnionArray[i];
179
180 (index)++;
181 }
182 } else {
183 int totalSize = index + size;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000184 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000185 if (!isDiagonalMatrixInit) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186 int count = 0;
187 for (int i = index; i < totalSize; i++) {
188 if (i >= instanceSize)
189 return;
190
191 leftUnionArray[i] = rightUnionArray[count];
192
193 (index)++;
194
195 if (node->getType().getObjectSize() > 1)
196 count++;
197 }
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000198 }
199 else
200 {
201 // for matrix diagonal constructors from a single scalar
202 for (int i = 0, col = 0; col < matrixCols; col++)
203 {
204 for (int row = 0; row < matrixRows; row++, i++)
205 {
206 if (col == row)
207 {
208 leftUnionArray[i] = rightUnionArray[0];
209 }
210 else
211 {
212 leftUnionArray[i].setFConst(0.0f);
213 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000215 (index)++;
216 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217 }
218 }
219 }
220}
221
222bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
223{
224 infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
225 error = true;
226 return false;
227}
228
229bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
230{
231 infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
232 error = true;
233 return false;
234}
235
236//
237// This function is the one to call externally to start the traversal.
238// Individual functions can be initialized to 0 to skip processing of that
239// type of node. It's children will still be processed.
240//
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000241bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242{
243 if (root == 0)
244 return false;
245
246 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
247
248 root->traverse(&it);
249 if (it.error)
250 return true;
251 else
252 return false;
253}