blob: f8fb6be57f4d2d671adfbd88db7c5be850689d46 [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
7#include "compiler/ParseHelper.h"
8
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;
64
65}
66
67bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
68{
69 TQualifier qualifier = node->getType().getQualifier();
70
71 if (qualifier != EvqConst) {
72 TString buf;
73 buf.append("'constructor' : assigning non-constant to ");
74 buf.append(type.getCompleteString());
75 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
76 error = true;
77 return false;
78 }
79
80 infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
81
82 return false;
83}
84
85bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
86{
87 TString buf;
88 buf.append("'constructor' : assigning non-constant to ");
89 buf.append(type.getCompleteString());
90 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
91 error = true;
92 return false;
93}
94
95bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
96{
97 if (!node->isConstructor() && node->getOp() != EOpComma) {
98 TString buf;
99 buf.append("'constructor' : assigning non-constant to ");
100 buf.append(type.getCompleteString());
101 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
102 error = true;
103 return false;
104 }
105
106 if (node->getSequence().size() == 0) {
107 error = true;
108 return false;
109 }
110
111 bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
112 if (flag)
113 {
114 singleConstantParam = true;
115 constructorType = node->getOp();
116 size = node->getType().getObjectSize();
117
118 if (node->getType().isMatrix()) {
119 isMatrix = true;
120 matrixSize = node->getType().getNominalSize();
121 }
122 }
123
124 for (TIntermSequence::iterator p = node->getSequence().begin();
125 p != node->getSequence().end(); p++) {
126
127 if (node->getOp() == EOpComma)
128 index = 0;
129
130 (*p)->traverse(this);
131 }
132 if (flag)
133 {
134 singleConstantParam = false;
135 constructorType = EOpNull;
136 size = 0;
137 isMatrix = false;
138 matrixSize = 0;
139 }
140 return false;
141}
142
143bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
144{
145 infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
146 error = true;
147 return false;
148}
149
150void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
151{
152 ConstantUnion* leftUnionArray = unionArray;
153 int instanceSize = type.getObjectSize();
154
155 if (index >= instanceSize)
156 return;
157
158 if (!singleConstantParam) {
159 int size = node->getType().getObjectSize();
160
161 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
162 for (int i=0; i < size; i++) {
163 if (index >= instanceSize)
164 return;
165 leftUnionArray[index] = rightUnionArray[i];
166
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
178 leftUnionArray[i] = rightUnionArray[count];
179
180 (index)++;
181
182 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 )
192 leftUnionArray[i] = rightUnionArray[count];
193 else
194 leftUnionArray[i].setFConst(0.0f);
195
196 (index)++;
197
198 if (node->getType().getObjectSize() > 1)
199 count++;
200 }
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}