blob: f141f544bd30a299b397e7d35624d087ea86995f [file] [log] [blame]
John Bauman89401822014-05-06 15:04:28 -04001//
John Baumand4ae8632014-05-06 16:18:33 -04002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
John Bauman89401822014-05-06 15:04:28 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Nicolas Capenscc863da2015-01-21 15:50:55 -05007#include "ParseHelper.h"
John Bauman89401822014-05-06 15:04:28 -04008
9//
10// Use this class to carry along data from node to node in
11// the traversal
12//
13class TConstTraverser : public TIntermTraverser {
14public:
John Baumand4ae8632014-05-06 16:18:33 -040015 TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TType& t)
John Bauman89401822014-05-06 15:04:28 -040016 : error(false),
17 index(0),
18 unionArray(cUnion),
19 type(t),
20 constructorType(constructType),
21 singleConstantParam(singleConstParam),
22 infoSink(sink),
John Bauman89401822014-05-06 15:04:28 -040023 size(0),
24 isMatrix(false),
25 matrixSize(0) {
26 }
27
28 bool error;
29
30protected:
31 void visitSymbol(TIntermSymbol*);
32 void visitConstantUnion(TIntermConstantUnion*);
33 bool visitBinary(Visit visit, TIntermBinary*);
34 bool visitUnary(Visit visit, TIntermUnary*);
35 bool visitSelection(Visit visit, TIntermSelection*);
36 bool visitAggregate(Visit visit, TIntermAggregate*);
37 bool visitLoop(Visit visit, TIntermLoop*);
38 bool visitBranch(Visit visit, TIntermBranch*);
39
40 int index;
41 ConstantUnion *unionArray;
42 TType type;
43 TOperator constructorType;
44 bool singleConstantParam;
45 TInfoSink& infoSink;
John Bauman89401822014-05-06 15:04:28 -040046 int size; // size of the constructor ( 4 for vec4)
47 bool isMatrix;
48 int matrixSize; // dimension of the matrix (nominal size and not the instance size)
49};
50
51//
52// The rest of the file are the traversal functions. The last one
53// is the one that starts the traversal.
54//
55// Return true from interior nodes to have the external traversal
56// continue on to children. If you process children yourself,
57// return false.
58//
59
60void TConstTraverser::visitSymbol(TIntermSymbol* node)
61{
62 infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
63 return;
John Bauman89401822014-05-06 15:04:28 -040064}
65
66bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
67{
68 TQualifier qualifier = node->getType().getQualifier();
Nicolas Capensc3bfb402014-06-12 11:45:17 -040069
Nicolas Capens31ad2aa2015-02-26 13:14:27 -050070 if (qualifier != EvqConstExpr) {
John Bauman89401822014-05-06 15:04:28 -040071 TString buf;
72 buf.append("'constructor' : assigning non-constant to ");
73 buf.append(type.getCompleteString());
74 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
75 error = true;
Nicolas Capensc3bfb402014-06-12 11:45:17 -040076 return false;
John Bauman89401822014-05-06 15:04:28 -040077 }
78
Nicolas Capensc3bfb402014-06-12 11:45:17 -040079 infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
80
John Bauman89401822014-05-06 15:04:28 -040081 return false;
82}
83
84bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
85{
86 TString buf;
87 buf.append("'constructor' : assigning non-constant to ");
88 buf.append(type.getCompleteString());
89 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
90 error = true;
Nicolas Capensc3bfb402014-06-12 11:45:17 -040091 return false;
John Bauman89401822014-05-06 15:04:28 -040092}
93
94bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
95{
96 if (!node->isConstructor() && node->getOp() != EOpComma) {
97 TString buf;
98 buf.append("'constructor' : assigning non-constant to ");
99 buf.append(type.getCompleteString());
100 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
101 error = true;
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400102 return false;
John Bauman89401822014-05-06 15:04:28 -0400103 }
104
105 if (node->getSequence().size() == 0) {
106 error = true;
107 return false;
108 }
109
110 bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400111 if (flag)
John Bauman89401822014-05-06 15:04:28 -0400112 {
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400113 singleConstantParam = true;
John Bauman89401822014-05-06 15:04:28 -0400114 constructorType = node->getOp();
115 size = node->getType().getObjectSize();
116
117 if (node->getType().isMatrix()) {
118 isMatrix = true;
119 matrixSize = node->getType().getNominalSize();
120 }
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400121 }
John Bauman89401822014-05-06 15:04:28 -0400122
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400123 for (TIntermSequence::iterator p = node->getSequence().begin();
John Bauman89401822014-05-06 15:04:28 -0400124 p != node->getSequence().end(); p++) {
125
126 if (node->getOp() == EOpComma)
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400127 index = 0;
John Bauman89401822014-05-06 15:04:28 -0400128
129 (*p)->traverse(this);
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400130 }
131 if (flag)
John Bauman89401822014-05-06 15:04:28 -0400132 {
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400133 singleConstantParam = false;
John Bauman89401822014-05-06 15:04:28 -0400134 constructorType = EOpNull;
135 size = 0;
136 isMatrix = false;
137 matrixSize = 0;
138 }
139 return false;
140}
141
142bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
143{
144 infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
145 error = true;
146 return false;
147}
148
149void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
150{
Nicolas Capens2e2ba8d2015-02-10 13:55:57 -0500151 if (!node->getUnionArrayPointer())
152 {
153 // The constant was not initialized, this should already have been logged
154 assert(infoSink.info.size() != 0);
155 return;
156 }
157
John Bauman89401822014-05-06 15:04:28 -0400158 ConstantUnion* leftUnionArray = unionArray;
159 int instanceSize = type.getObjectSize();
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400160 TBasicType basicType = type.getBasicType();
John Bauman89401822014-05-06 15:04:28 -0400161
162 if (index >= instanceSize)
163 return;
164
165 if (!singleConstantParam) {
166 int size = node->getType().getObjectSize();
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400167
John Bauman89401822014-05-06 15:04:28 -0400168 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
169 for (int i=0; i < size; i++) {
170 if (index >= instanceSize)
171 return;
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400172 leftUnionArray[index].cast(basicType, rightUnionArray[i]);
John Bauman89401822014-05-06 15:04:28 -0400173
174 (index)++;
175 }
176 } else {
177 int totalSize = index + size;
178 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
179 if (!isMatrix) {
180 int count = 0;
181 for (int i = index; i < totalSize; i++) {
182 if (i >= instanceSize)
183 return;
184
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400185 leftUnionArray[i].cast(basicType, rightUnionArray[count]);
John Bauman89401822014-05-06 15:04:28 -0400186
187 (index)++;
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400188
John Bauman89401822014-05-06 15:04:28 -0400189 if (node->getType().getObjectSize() > 1)
190 count++;
191 }
192 } else { // for matrix constructors
193 int count = 0;
194 int element = index;
195 for (int i = index; i < totalSize; i++) {
196 if (i >= instanceSize)
197 return;
198 if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400199 leftUnionArray[i].cast(basicType, rightUnionArray[0]);
200 else
John Bauman89401822014-05-06 15:04:28 -0400201 leftUnionArray[i].setFConst(0.0f);
202
203 (index)++;
204
205 if (node->getType().getObjectSize() > 1)
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400206 count++;
John Bauman89401822014-05-06 15:04:28 -0400207 }
208 }
209 }
210}
211
212bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
213{
214 infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
215 error = true;
216 return false;
217}
218
219bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
220{
221 infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
222 error = true;
223 return false;
224}
225
226//
227// This function is the one to call externally to start the traversal.
228// Individual functions can be initialized to 0 to skip processing of that
229// type of node. It's children will still be processed.
230//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400231bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam)
John Bauman89401822014-05-06 15:04:28 -0400232{
233 if (root == 0)
234 return false;
235
John Baumand4ae8632014-05-06 16:18:33 -0400236 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t);
John Bauman89401822014-05-06 15:04:28 -0400237
238 root->traverse(&it);
239 if (it.error)
240 return true;
241 else
242 return false;
243}