blob: 0a6f7af8556eab20ada5060eef3b9b169d98d036 [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//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070010// Use this class to carry along data from node to node in
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011// the traversal
12//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070013class TConstTraverser : public TIntermTraverser
14{
15 public:
Jamie Madill6ba6ead2015-05-04 14:21:21 -040016 TConstTraverser(TConstantUnion *cUnion, bool singleConstParam,
Zhenyao Moe40d1e92014-07-16 17:40:36 -070017 TOperator constructType, TInfoSink &sink, TType &t)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +030018 : TIntermTraverser(true, false, false),
19 error(false),
Zhenyao Moe40d1e92014-07-16 17:40:36 -070020 mIndex(0),
21 mUnionArray(cUnion),
22 mType(t),
23 mConstructorType(constructType),
24 mSingleConstantParam(singleConstParam),
25 mInfoSink(sink),
26 mSize(0),
27 mIsDiagonalMatrixInit(false),
28 mMatrixCols(0),
29 mMatrixRows(0)
30 {
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000031 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000033 bool error;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034
Zhenyao Moe40d1e92014-07-16 17:40:36 -070035 protected:
Corentin Walleze5a1f272015-08-21 02:58:25 +020036 void visitSymbol(TIntermSymbol *) override;
37 void visitConstantUnion(TIntermConstantUnion *) override;
38 bool visitBinary(Visit visit, TIntermBinary *) override;
39 bool visitUnary(Visit visit, TIntermUnary *) override;
40 bool visitSelection(Visit visit, TIntermSelection *) override;
41 bool visitAggregate(Visit visit, TIntermAggregate *) override;
42 bool visitLoop(Visit visit, TIntermLoop *) override;
43 bool visitBranch(Visit visit, TIntermBranch *) override;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000044
Zhenyao Moe40d1e92014-07-16 17:40:36 -070045 size_t mIndex;
Jamie Madill6ba6ead2015-05-04 14:21:21 -040046 TConstantUnion *mUnionArray;
Zhenyao Moe40d1e92014-07-16 17:40:36 -070047 TType mType;
48 TOperator mConstructorType;
49 bool mSingleConstantParam;
50 TInfoSink &mInfoSink;
51 size_t mSize; // size of the constructor ( 4 for vec4)
52 bool mIsDiagonalMatrixInit;
53 int mMatrixCols; // columns of the matrix
54 int mMatrixRows; // rows of the matrix
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055};
56
57//
58// The rest of the file are the traversal functions. The last one
59// is the one that starts the traversal.
60//
61// Return true from interior nodes to have the external traversal
62// continue on to children. If you process children yourself,
63// return false.
64//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070065void TConstTraverser::visitSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000066{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070067 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
68 "Symbol Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000070}
71
Zhenyao Moe40d1e92014-07-16 17:40:36 -070072bool TConstTraverser::visitBinary(Visit visit, TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000073{
74 TQualifier qualifier = node->getType().getQualifier();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070075
76 if (qualifier != EvqConst)
77 {
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000078 TString buf;
79 buf.append("'constructor' : assigning non-constant to ");
Zhenyao Moe40d1e92014-07-16 17:40:36 -070080 buf.append(mType.getCompleteString());
81 mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000082 error = true;
83 return false;
84 }
85
Zhenyao Moe40d1e92014-07-16 17:40:36 -070086 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
87 "Binary Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088 return false;
89}
90
Zhenyao Moe40d1e92014-07-16 17:40:36 -070091bool TConstTraverser::visitUnary(Visit visit, TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070093 TString buf;
94 buf.append("'constructor' : assigning non-constant to ");
95 buf.append(mType.getCompleteString());
96 mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097 error = true;
98 return false;
99}
100
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700101bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
102{
103 if (!node->isConstructor() && node->getOp() != EOpComma)
104 {
105 TString buf;
106 buf.append("'constructor' : assigning non-constant to ");
107 buf.append(mType.getCompleteString());
108 mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
109 error = true;
110 return false;
111 }
112
113 if (node->getSequence()->size() == 0)
114 {
115 error = true;
116 return false;
117 }
118
119 bool flag = node->getSequence()->size() == 1 &&
120 (*node->getSequence())[0]->getAsTyped()->getAsConstantUnion();
121 if (flag)
122 {
123 mSingleConstantParam = true;
124 mConstructorType = node->getOp();
125 mSize = node->getType().getObjectSize();
126
127 if (node->getType().isMatrix())
128 {
129 mIsDiagonalMatrixInit = true;
130 mMatrixCols = node->getType().getCols();
131 mMatrixRows = node->getType().getRows();
132 }
133 }
134
135 for (TIntermSequence::iterator p = node->getSequence()->begin();
136 p != node->getSequence()->end(); p++)
137 {
138 if (node->getOp() == EOpComma)
139 mIndex = 0;
140 (*p)->traverse(this);
141 }
142 if (flag)
143 {
144 mSingleConstantParam = false;
145 mConstructorType = EOpNull;
146 mSize = 0;
147 mIsDiagonalMatrixInit = false;
148 mMatrixCols = 0;
149 mMatrixRows = 0;
150 }
151 return false;
152}
153
154bool TConstTraverser::visitSelection(Visit visit, TIntermSelection *node)
155{
156 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
157 "Selection Node found in constant constructor");
158 error = true;
159 return false;
160}
161
162void TConstTraverser::visitConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000163{
shannon.woods%transgaming.com@gtempaccount.com6df256c2013-04-13 03:29:46 +0000164 if (!node->getUnionArrayPointer())
165 {
166 // The constant was not initialized, this should already have been logged
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700167 ASSERT(mInfoSink.info.size() != 0);
shannon.woods%transgaming.com@gtempaccount.com6df256c2013-04-13 03:29:46 +0000168 return;
169 }
170
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400171 TConstantUnion *leftUnionArray = mUnionArray;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700172 size_t instanceSize = mType.getObjectSize();
173 TBasicType basicType = mType.getBasicType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700175 if (mIndex >= instanceSize)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176 return;
177
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700178 if (!mSingleConstantParam)
179 {
Jamie Madill94bf7f22013-07-08 13:31:15 -0400180 size_t objectSize = node->getType().getObjectSize();
Jamie Madillb11e2482015-05-04 14:21:22 -0400181 const TConstantUnion *rightUnionArray = node->getUnionArrayPointer();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700182 for (size_t i=0; i < objectSize; i++)
183 {
184 if (mIndex >= instanceSize)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185 return;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700186 leftUnionArray[mIndex].cast(basicType, rightUnionArray[i]);
187 mIndex++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700189 }
190 else
191 {
192 size_t totalSize = mIndex + mSize;
Jamie Madillb11e2482015-05-04 14:21:22 -0400193 const TConstantUnion *rightUnionArray = node->getUnionArrayPointer();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700194 if (!mIsDiagonalMatrixInit)
195 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000196 int count = 0;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700197 for (size_t i = mIndex; i < totalSize; i++)
198 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199 if (i >= instanceSize)
200 return;
Nicolas Capens01df23e2014-06-11 10:56:03 -0400201 leftUnionArray[i].cast(basicType, rightUnionArray[count]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700202 mIndex++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203 if (node->getType().getObjectSize() > 1)
204 count++;
205 }
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000206 }
207 else
208 {
209 // for matrix diagonal constructors from a single scalar
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700210 for (int i = 0, col = 0; col < mMatrixCols; col++)
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000211 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700212 for (int row = 0; row < mMatrixRows; row++, i++)
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000213 {
214 if (col == row)
215 {
Nicolas Capens01df23e2014-06-11 10:56:03 -0400216 leftUnionArray[i].cast(basicType, rightUnionArray[0]);
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000217 }
218 else
219 {
220 leftUnionArray[i].setFConst(0.0f);
221 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700222 mIndex++;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000223 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224 }
225 }
226 }
227}
228
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700229bool TConstTraverser::visitLoop(Visit visit, TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700231 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
232 "Loop Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233 error = true;
234 return false;
235}
236
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700237bool TConstTraverser::visitBranch(Visit visit, TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700239 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
240 "Branch Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241 error = true;
242 return false;
243}
244
245//
246// This function is the one to call externally to start the traversal.
247// Individual functions can be initialized to 0 to skip processing of that
248// type of node. It's children will still be processed.
249//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700250bool TIntermediate::parseConstTree(
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400251 const TSourceLoc &line, TIntermNode *root, TConstantUnion *unionArray,
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700252 TOperator constructorType, TType t, bool singleConstantParam)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253{
254 if (root == 0)
255 return false;
256
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700257 TConstTraverser it(unionArray, singleConstantParam, constructorType,
258 mInfoSink, t);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259
260 root->traverse(&it);
261 if (it.error)
262 return true;
263 else
264 return false;
265}