blob: 1897ed151c1ac8500458167610201e7ce5d47f59 [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:
16 TConstTraverser(ConstantUnion *cUnion, bool singleConstParam,
17 TOperator constructType, TInfoSink &sink, TType &t)
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000018 : error(false),
Zhenyao Moe40d1e92014-07-16 17:40:36 -070019 mIndex(0),
20 mUnionArray(cUnion),
21 mType(t),
22 mConstructorType(constructType),
23 mSingleConstantParam(singleConstParam),
24 mInfoSink(sink),
25 mSize(0),
26 mIsDiagonalMatrixInit(false),
27 mMatrixCols(0),
28 mMatrixRows(0)
29 {
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000030 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031
alokp@chromium.orgb2dfd8e2010-08-09 22:28:19 +000032 bool error;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033
Zhenyao Moe40d1e92014-07-16 17:40:36 -070034 protected:
35 void visitSymbol(TIntermSymbol *);
36 void visitConstantUnion(TIntermConstantUnion *);
37 bool visitBinary(Visit visit, TIntermBinary *);
38 bool visitUnary(Visit visit, TIntermUnary *);
39 bool visitSelection(Visit visit, TIntermSelection *);
40 bool visitAggregate(Visit visit, TIntermAggregate *);
41 bool visitLoop(Visit visit, TIntermLoop *);
42 bool visitBranch(Visit visit, TIntermBranch *);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043
Zhenyao Moe40d1e92014-07-16 17:40:36 -070044 size_t mIndex;
45 ConstantUnion *mUnionArray;
46 TType mType;
47 TOperator mConstructorType;
48 bool mSingleConstantParam;
49 TInfoSink &mInfoSink;
50 size_t mSize; // size of the constructor ( 4 for vec4)
51 bool mIsDiagonalMatrixInit;
52 int mMatrixCols; // columns of the matrix
53 int mMatrixRows; // rows of the matrix
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000054};
55
56//
57// The rest of the file are the traversal functions. The last one
58// is the one that starts the traversal.
59//
60// Return true from interior nodes to have the external traversal
61// continue on to children. If you process children yourself,
62// return false.
63//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070064void TConstTraverser::visitSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000065{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070066 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
67 "Symbol Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000068 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069}
70
Zhenyao Moe40d1e92014-07-16 17:40:36 -070071bool TConstTraverser::visitBinary(Visit visit, TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000072{
73 TQualifier qualifier = node->getType().getQualifier();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070074
75 if (qualifier != EvqConst)
76 {
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000077 TString buf;
78 buf.append("'constructor' : assigning non-constant to ");
Zhenyao Moe40d1e92014-07-16 17:40:36 -070079 buf.append(mType.getCompleteString());
80 mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081 error = true;
82 return false;
83 }
84
Zhenyao Moe40d1e92014-07-16 17:40:36 -070085 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
86 "Binary Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087 return false;
88}
89
Zhenyao Moe40d1e92014-07-16 17:40:36 -070090bool TConstTraverser::visitUnary(Visit visit, TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070092 TString buf;
93 buf.append("'constructor' : assigning non-constant to ");
94 buf.append(mType.getCompleteString());
95 mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096 error = true;
97 return false;
98}
99
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700100bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
101{
102 if (!node->isConstructor() && node->getOp() != EOpComma)
103 {
104 TString buf;
105 buf.append("'constructor' : assigning non-constant to ");
106 buf.append(mType.getCompleteString());
107 mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
108 error = true;
109 return false;
110 }
111
112 if (node->getSequence()->size() == 0)
113 {
114 error = true;
115 return false;
116 }
117
118 bool flag = node->getSequence()->size() == 1 &&
119 (*node->getSequence())[0]->getAsTyped()->getAsConstantUnion();
120 if (flag)
121 {
122 mSingleConstantParam = true;
123 mConstructorType = node->getOp();
124 mSize = node->getType().getObjectSize();
125
126 if (node->getType().isMatrix())
127 {
128 mIsDiagonalMatrixInit = true;
129 mMatrixCols = node->getType().getCols();
130 mMatrixRows = node->getType().getRows();
131 }
132 }
133
134 for (TIntermSequence::iterator p = node->getSequence()->begin();
135 p != node->getSequence()->end(); p++)
136 {
137 if (node->getOp() == EOpComma)
138 mIndex = 0;
139 (*p)->traverse(this);
140 }
141 if (flag)
142 {
143 mSingleConstantParam = false;
144 mConstructorType = EOpNull;
145 mSize = 0;
146 mIsDiagonalMatrixInit = false;
147 mMatrixCols = 0;
148 mMatrixRows = 0;
149 }
150 return false;
151}
152
153bool TConstTraverser::visitSelection(Visit visit, TIntermSelection *node)
154{
155 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
156 "Selection Node found in constant constructor");
157 error = true;
158 return false;
159}
160
161void TConstTraverser::visitConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162{
shannon.woods%transgaming.com@gtempaccount.com6df256c2013-04-13 03:29:46 +0000163 if (!node->getUnionArrayPointer())
164 {
165 // The constant was not initialized, this should already have been logged
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700166 ASSERT(mInfoSink.info.size() != 0);
shannon.woods%transgaming.com@gtempaccount.com6df256c2013-04-13 03:29:46 +0000167 return;
168 }
169
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700170 ConstantUnion *leftUnionArray = mUnionArray;
171 size_t instanceSize = mType.getObjectSize();
172 TBasicType basicType = mType.getBasicType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700174 if (mIndex >= instanceSize)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175 return;
176
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700177 if (!mSingleConstantParam)
178 {
Jamie Madill94bf7f22013-07-08 13:31:15 -0400179 size_t objectSize = node->getType().getObjectSize();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000180 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700181 for (size_t i=0; i < objectSize; i++)
182 {
183 if (mIndex >= instanceSize)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184 return;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700185 leftUnionArray[mIndex].cast(basicType, rightUnionArray[i]);
186 mIndex++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700188 }
189 else
190 {
191 size_t totalSize = mIndex + mSize;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000192 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700193 if (!mIsDiagonalMatrixInit)
194 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195 int count = 0;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700196 for (size_t i = mIndex; i < totalSize; i++)
197 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198 if (i >= instanceSize)
199 return;
Nicolas Capens01df23e2014-06-11 10:56:03 -0400200 leftUnionArray[i].cast(basicType, rightUnionArray[count]);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700201 mIndex++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202 if (node->getType().getObjectSize() > 1)
203 count++;
204 }
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000205 }
206 else
207 {
208 // for matrix diagonal constructors from a single scalar
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700209 for (int i = 0, col = 0; col < mMatrixCols; col++)
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000210 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700211 for (int row = 0; row < mMatrixRows; row++, i++)
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000212 {
213 if (col == row)
214 {
Nicolas Capens01df23e2014-06-11 10:56:03 -0400215 leftUnionArray[i].cast(basicType, rightUnionArray[0]);
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000216 }
217 else
218 {
219 leftUnionArray[i].setFConst(0.0f);
220 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700221 mIndex++;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000222 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223 }
224 }
225 }
226}
227
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700228bool TConstTraverser::visitLoop(Visit visit, TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700230 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
231 "Loop Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000232 error = true;
233 return false;
234}
235
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700236bool TConstTraverser::visitBranch(Visit visit, TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700238 mInfoSink.info.message(EPrefixInternalError, node->getLine(),
239 "Branch Node found in constant constructor");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240 error = true;
241 return false;
242}
243
244//
245// This function is the one to call externally to start the traversal.
246// Individual functions can be initialized to 0 to skip processing of that
247// type of node. It's children will still be processed.
248//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700249bool TIntermediate::parseConstTree(
250 const TSourceLoc &line, TIntermNode *root, ConstantUnion *unionArray,
251 TOperator constructorType, TType t, bool singleConstantParam)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252{
253 if (root == 0)
254 return false;
255
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700256 TConstTraverser it(unionArray, singleConstantParam, constructorType,
257 mInfoSink, t);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258
259 root->traverse(&it);
260 if (it.error)
261 return true;
262 else
263 return false;
264}