blob: 833d429387b850e25bc296a826a7eddec1f51ebe [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00007#include "compiler/ParseHelper.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00008
9//
10// Use this class to carry along data from node to node in
11// the traversal
12//
13class TConstTraverser : public TIntermTraverser {
14public:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +000015 TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) : unionArray(cUnion), type(t),
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000016 constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), symbolTable(symTable), error(false), isMatrix(false), matrixSize(0)
17 {
18 index = 0;
19 }
20
21 bool error;
22
23protected:
24 void visitSymbol(TIntermSymbol*);
25 void visitConstantUnion(TIntermConstantUnion*);
26 bool visitBinary(Visit visit, TIntermBinary*);
27 bool visitUnary(Visit visit, TIntermUnary*);
28 bool visitSelection(Visit visit, TIntermSelection*);
29 bool visitAggregate(Visit visit, TIntermAggregate*);
30 bool visitLoop(Visit visit, TIntermLoop*);
31 bool visitBranch(Visit visit, TIntermBranch*);
32
33 int index;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +000034 ConstantUnion *unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035 TType type;
36 TOperator constructorType;
37 bool singleConstantParam;
38 TInfoSink& infoSink;
39 TSymbolTable& symbolTable;
40 int size; // size of the constructor ( 4 for vec4)
41 bool isMatrix;
42 int matrixSize; // dimension of the matrix (nominal size and not the instance size)
43};
44
45//
46// The rest of the file are the traversal functions. The last one
47// is the one that starts the traversal.
48//
49// Return true from interior nodes to have the external traversal
50// continue on to children. If you process children yourself,
51// return false.
52//
53
54void TConstTraverser::visitSymbol(TIntermSymbol* node)
55{
56 infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine());
57 return;
58
59}
60
61bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
62{
63 TQualifier qualifier = node->getType().getQualifier();
64
65 if (qualifier != EvqConst) {
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000066 TString buf;
67 buf.append("'constructor' : assigning non-constant to ");
68 buf.append(type.getCompleteString());
69 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000070 error = true;
71 return false;
72 }
73
74 infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
75
76 return false;
77}
78
79bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
80{
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000081 TString buf;
82 buf.append("'constructor' : assigning non-constant to ");
83 buf.append(type.getCompleteString());
84 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085 error = true;
86 return false;
87}
88
89bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
90{
91 if (!node->isConstructor() && node->getOp() != EOpComma) {
alokp@chromium.org4e4facd2010-06-02 15:21:22 +000092 TString buf;
93 buf.append("'constructor' : assigning non-constant to ");
94 buf.append(type.getCompleteString());
95 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096 error = true;
97 return false;
98 }
99
100 if (node->getSequence().size() == 0) {
101 error = true;
102 return false;
103 }
104
105 bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
106 if (flag)
107 {
108 singleConstantParam = true;
109 constructorType = node->getOp();
110 size = node->getType().getObjectSize();
111
112 if (node->getType().isMatrix()) {
113 isMatrix = true;
114 matrixSize = node->getType().getNominalSize();
115 }
116 }
117
118 for (TIntermSequence::iterator p = node->getSequence().begin();
119 p != node->getSequence().end(); p++) {
120
121 if (node->getOp() == EOpComma)
122 index = 0;
123
124 (*p)->traverse(this);
125 }
126 if (flag)
127 {
128 singleConstantParam = false;
129 constructorType = EOpNull;
130 size = 0;
131 isMatrix = false;
132 matrixSize = 0;
133 }
134 return false;
135}
136
137bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
138{
139 infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
140 error = true;
141 return false;
142}
143
144void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
145{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000146 ConstantUnion* leftUnionArray = unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147 int instanceSize = type.getObjectSize();
148
149 if (index >= instanceSize)
150 return;
151
152 if (!singleConstantParam) {
153 int size = node->getType().getObjectSize();
154
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000155 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000156 for (int i=0; i < size; i++) {
157 if (index >= instanceSize)
158 return;
159 leftUnionArray[index] = rightUnionArray[i];
160
161 (index)++;
162 }
163 } else {
164 int totalSize = index + size;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000165 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166 if (!isMatrix) {
167 int count = 0;
168 for (int i = index; i < totalSize; i++) {
169 if (i >= instanceSize)
170 return;
171
172 leftUnionArray[i] = rightUnionArray[count];
173
174 (index)++;
175
176 if (node->getType().getObjectSize() > 1)
177 count++;
178 }
179 } else { // for matrix constructors
180 int count = 0;
181 int element = index;
182 for (int i = index; i < totalSize; i++) {
183 if (i >= instanceSize)
184 return;
185 if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
186 leftUnionArray[i] = rightUnionArray[count];
187 else
188 leftUnionArray[i].setFConst(0.0f);
189
daniel@transgaming.com49bce7e2010-03-17 03:58:51 +0000190 (index)++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191
192 if (node->getType().getObjectSize() > 1)
193 count++;
194 }
195 }
196 }
197}
198
199bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
200{
201 infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
202 error = true;
203 return false;
204}
205
206bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
207{
208 infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
209 error = true;
210 return false;
211}
212
213//
214// This function is the one to call externally to start the traversal.
215// Individual functions can be initialized to 0 to skip processing of that
216// type of node. It's children will still be processed.
217//
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000218bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219{
220 if (root == 0)
221 return false;
222
223 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
224
225 root->traverse(&it);
226 if (it.error)
227 return true;
228 else
229 return false;
230}