blob: 05cf91247537e0d3265fa8105c382e7638ec078f [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens01df23e2014-06-11 10:56:03 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Jamie Madill6b9cb252013-10-17 10:45:47 -04007#include "compiler/translator/ParseContext.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:
shannonwoods@chromium.org298f9072013-05-30 00:21:17 +000015 TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t)
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000016 : error(false),
17 index(0),
18 unionArray(cUnion),
19 type(t),
20 constructorType(constructType),
21 singleConstantParam(singleConstParam),
22 infoSink(sink),
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000023 size(0),
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +000024 isDiagonalMatrixInit(false),
25 matrixCols(0),
26 matrixRows(0) {
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000027 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000028
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000029 bool error;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
31protected:
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000032 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*);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000040
Jamie Madill94bf7f22013-07-08 13:31:15 -040041 size_t index;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +000042 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043 TType type;
44 TOperator constructorType;
45 bool singleConstantParam;
46 TInfoSink& infoSink;
Jamie Madill94bf7f22013-07-08 13:31:15 -040047 size_t size; // size of the constructor ( 4 for vec4)
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +000048 bool isDiagonalMatrixInit;
49 int matrixCols; // columns of the matrix
50 int matrixRows; // rows of the matrix
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000051};
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
62void TConstTraverser::visitSymbol(TIntermSymbol* node)
63{
Jamie Madill075edd82013-07-08 13:30:19 -040064 infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000065 return;
66
67}
68
69bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
70{
71 TQualifier qualifier = node->getType().getQualifier();
72
73 if (qualifier != EvqConst) {
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000074 TString buf;
75 buf.append("'constructor' : assigning non-constant to ");
76 buf.append(type.getCompleteString());
Jamie Madill075edd82013-07-08 13:30:19 -040077 infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000078 error = true;
79 return false;
80 }
81
Jamie Madill075edd82013-07-08 13:30:19 -040082 infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083
84 return false;
85}
86
87bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
88{
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000089 TString buf;
90 buf.append("'constructor' : assigning non-constant to ");
91 buf.append(type.getCompleteString());
Jamie Madill075edd82013-07-08 13:30:19 -040092 infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000093 error = true;
94 return false;
95}
96
97bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
98{
99 if (!node->isConstructor() && node->getOp() != EOpComma) {
alokp@chromium.org4e4facd2010-06-02 15:21:22 +0000100 TString buf;
101 buf.append("'constructor' : assigning non-constant to ");
102 buf.append(type.getCompleteString());
Jamie Madill075edd82013-07-08 13:30:19 -0400103 infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104 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()) {
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000121 isDiagonalMatrixInit = true;
122 matrixCols = node->getType().getCols();
123 matrixRows = node->getType().getRows();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124 }
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;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000140 isDiagonalMatrixInit = false;
141 matrixCols = 0;
142 matrixRows = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143 }
144 return false;
145}
146
147bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
148{
Jamie Madill075edd82013-07-08 13:30:19 -0400149 infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150 error = true;
151 return false;
152}
153
154void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
155{
shannon.woods%transgaming.com@gtempaccount.com6df256c2013-04-13 03:29:46 +0000156 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
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000163 ConstantUnion* leftUnionArray = unionArray;
Jamie Madill94bf7f22013-07-08 13:31:15 -0400164 size_t instanceSize = type.getObjectSize();
Nicolas Capens01df23e2014-06-11 10:56:03 -0400165 TBasicType basicType = type.getBasicType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166
167 if (index >= instanceSize)
168 return;
169
170 if (!singleConstantParam) {
Jamie Madill94bf7f22013-07-08 13:31:15 -0400171 size_t objectSize = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000173 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
Jamie Madill94bf7f22013-07-08 13:31:15 -0400174 for (size_t i=0; i < objectSize; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175 if (index >= instanceSize)
176 return;
Nicolas Capens01df23e2014-06-11 10:56:03 -0400177 leftUnionArray[index].cast(basicType, rightUnionArray[i]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178
179 (index)++;
180 }
181 } else {
Jamie Madill94bf7f22013-07-08 13:31:15 -0400182 size_t totalSize = index + size;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000183 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000184 if (!isDiagonalMatrixInit) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185 int count = 0;
Jamie Madill94bf7f22013-07-08 13:31:15 -0400186 for (size_t i = index; i < totalSize; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187 if (i >= instanceSize)
188 return;
189
Nicolas Capens01df23e2014-06-11 10:56:03 -0400190 leftUnionArray[i].cast(basicType, rightUnionArray[count]);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191
192 (index)++;
193
194 if (node->getType().getObjectSize() > 1)
195 count++;
196 }
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000197 }
198 else
199 {
200 // for matrix diagonal constructors from a single scalar
201 for (int i = 0, col = 0; col < matrixCols; col++)
202 {
203 for (int row = 0; row < matrixRows; row++, i++)
204 {
205 if (col == row)
206 {
Nicolas Capens01df23e2014-06-11 10:56:03 -0400207 leftUnionArray[i].cast(basicType, rightUnionArray[0]);
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000208 }
209 else
210 {
211 leftUnionArray[i].setFConst(0.0f);
212 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000214 (index)++;
215 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216 }
217 }
218 }
219}
220
221bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
222{
Jamie Madill075edd82013-07-08 13:30:19 -0400223 infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224 error = true;
225 return false;
226}
227
228bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
229{
Jamie Madill075edd82013-07-08 13:30:19 -0400230 infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000231 error = true;
232 return false;
233}
234
235//
236// This function is the one to call externally to start the traversal.
237// Individual functions can be initialized to 0 to skip processing of that
238// type of node. It's children will still be processed.
239//
Jamie Madill075edd82013-07-08 13:30:19 -0400240bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241{
242 if (root == 0)
243 return false;
244
shannonwoods@chromium.org298f9072013-05-30 00:21:17 +0000245 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000246
247 root->traverse(&it);
248 if (it.error)
249 return true;
250 else
251 return false;
252}