blob: d14babf02f8ddc2fafa418800cc641ca63352d36 [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
John Bauman89401822014-05-06 15:04:28 -040070 if (qualifier != EvqConst) {
71 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{
151 ConstantUnion* leftUnionArray = unionArray;
152 int instanceSize = type.getObjectSize();
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400153 TBasicType basicType = type.getBasicType();
John Bauman89401822014-05-06 15:04:28 -0400154
155 if (index >= instanceSize)
156 return;
157
158 if (!singleConstantParam) {
159 int size = node->getType().getObjectSize();
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400160
John Bauman89401822014-05-06 15:04:28 -0400161 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
162 for (int i=0; i < size; i++) {
163 if (index >= instanceSize)
164 return;
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400165 leftUnionArray[index].cast(basicType, rightUnionArray[i]);
John Bauman89401822014-05-06 15:04:28 -0400166
167 (index)++;
168 }
169 } else {
170 int totalSize = index + size;
171 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
172 if (!isMatrix) {
173 int count = 0;
174 for (int i = index; i < totalSize; i++) {
175 if (i >= instanceSize)
176 return;
177
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400178 leftUnionArray[i].cast(basicType, rightUnionArray[count]);
John Bauman89401822014-05-06 15:04:28 -0400179
180 (index)++;
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400181
John Bauman89401822014-05-06 15:04:28 -0400182 if (node->getType().getObjectSize() > 1)
183 count++;
184 }
185 } else { // for matrix constructors
186 int count = 0;
187 int element = index;
188 for (int i = index; i < totalSize; i++) {
189 if (i >= instanceSize)
190 return;
191 if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400192 leftUnionArray[i].cast(basicType, rightUnionArray[0]);
193 else
John Bauman89401822014-05-06 15:04:28 -0400194 leftUnionArray[i].setFConst(0.0f);
195
196 (index)++;
197
198 if (node->getType().getObjectSize() > 1)
Nicolas Capensc3bfb402014-06-12 11:45:17 -0400199 count++;
John Bauman89401822014-05-06 15:04:28 -0400200 }
201 }
202 }
203}
204
205bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
206{
207 infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
208 error = true;
209 return false;
210}
211
212bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
213{
214 infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
215 error = true;
216 return false;
217}
218
219//
220// This function is the one to call externally to start the traversal.
221// Individual functions can be initialized to 0 to skip processing of that
222// type of node. It's children will still be processed.
223//
John Baumand4ae8632014-05-06 16:18:33 -0400224bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TType t, bool singleConstantParam)
John Bauman89401822014-05-06 15:04:28 -0400225{
226 if (root == 0)
227 return false;
228
John Baumand4ae8632014-05-06 16:18:33 -0400229 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, t);
John Bauman89401822014-05-06 15:04:28 -0400230
231 root->traverse(&it);
232 if (it.error)
233 return true;
234 else
235 return false;
236}