Fix variable scoping of do-while
[platform/upstream/glslang.git] / glslang / MachineIndependent / parseConst.cpp
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions
7 // are met:
8 //
9 //    Redistributions of source code must retain the above copyright
10 //    notice, this list of conditions and the following disclaimer.
11 //
12 //    Redistributions in binary form must reproduce the above
13 //    copyright notice, this list of conditions and the following
14 //    disclaimer in the documentation and/or other materials provided
15 //    with the distribution.
16 //
17 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
18 //    contributors may be used to endorse or promote products derived
19 //    from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 // POSSIBILITY OF SUCH DAMAGE.
33 //
34
35 //
36 // Traverse a tree of constants to create a single folded constant.
37 // It should only be used when the whole tree is known to be constant.
38 //
39
40 #include "ParseHelper.h"
41
42 namespace glslang {
43
44 class TConstTraverser : public TIntermTraverser {
45 public:
46     TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
47       : unionArray(cUnion), type(t),
48         constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
49         matrixCols(0), matrixRows(0) {  index = 0; tOp = EOpNull; }
50
51     virtual void visitConstantUnion(TIntermConstantUnion* node);
52     virtual bool visitAggregate(TVisit, TIntermAggregate* node);
53
54     int index;
55     TConstUnionArray unionArray;
56     TOperator tOp;
57     const TType& type;
58     TOperator constructorType;
59     bool singleConstantParam;
60     bool error;
61     int size; // size of the constructor ( 4 for vec4)
62     bool isMatrix;
63     int matrixCols;
64     int matrixRows;
65
66 protected:
67     TConstTraverser(TConstTraverser&);
68     TConstTraverser& operator=(TConstTraverser&);
69 };
70
71 bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
72 {
73     if (! node->isConstructor() && node->getOp() != EOpComma) {
74         error = true;
75
76         return false;
77     }
78
79     bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
80     if (flag) {
81         singleConstantParam = true;
82         constructorType = node->getOp();
83         size = node->getType().computeNumComponents();
84
85         if (node->getType().isMatrix()) {
86             isMatrix = true;
87             matrixCols = node->getType().getMatrixCols();
88             matrixRows = node->getType().getMatrixRows();
89         }
90     }
91
92     for (TIntermSequence::iterator p = node->getSequence().begin();
93                                    p != node->getSequence().end(); p++) {
94
95         if (node->getOp() == EOpComma)
96             index = 0;
97
98         (*p)->traverse(this);
99     }
100     if (flag)
101     {
102         singleConstantParam = false;
103         constructorType = EOpNull;
104         size = 0;
105         isMatrix = false;
106         matrixCols = 0;
107         matrixRows = 0;
108     }
109
110     return false;
111 }
112
113 void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
114 {
115     TConstUnionArray leftUnionArray(unionArray);
116     int instanceSize = type.computeNumComponents();
117
118     if (index >= instanceSize)
119         return;
120
121     if (! singleConstantParam) {
122         int rightUnionSize = node->getType().computeNumComponents();
123
124         const TConstUnionArray& rightUnionArray = node->getConstArray();
125         for (int i = 0; i < rightUnionSize; i++) {
126             if (index >= instanceSize)
127                 return;
128             leftUnionArray[index] = rightUnionArray[i];
129
130             index++;
131         }
132     } else {
133         int endIndex = index + size;
134         const TConstUnionArray& rightUnionArray = node->getConstArray();
135         if (! isMatrix) {
136             int count = 0;
137             int nodeComps = node->getType().computeNumComponents();
138             for (int i = index; i < endIndex; i++) {
139                 if (i >= instanceSize)
140                     return;
141
142                 leftUnionArray[i] = rightUnionArray[count];
143
144                 (index)++;
145
146                 if (nodeComps > 1)
147                     count++;
148             }
149         } else {
150             // constructing a matrix, but from what?
151             if (node->isMatrix()) {
152                 // Matrix from a matrix; this has the outer matrix, node is the argument matrix.
153                 // Traverse the outer, potentially bigger matrix, fill in missing pieces with the
154                 // identity matrix.
155                 for (int c = 0; c < matrixCols; ++c) {
156                     for (int r = 0; r < matrixRows; ++r) {
157                         int targetOffset = index + c * matrixRows + r;
158                         if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
159                             int srcOffset = c * node->getType().getMatrixRows() + r;
160                             leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
161                         } else if (r == c)
162                             leftUnionArray[targetOffset].setDConst(1.0);
163                         else
164                             leftUnionArray[targetOffset].setDConst(0.0);
165                     }
166                 }
167             } else {
168                 // matrix from vector or scalar
169                 int nodeComps = node->getType().computeNumComponents();
170                 if (nodeComps == 1) {
171                     for (int c = 0; c < matrixCols; ++c) {
172                         for (int r = 0; r < matrixRows; ++r) {
173                             if (r == c)
174                                 leftUnionArray[index] = rightUnionArray[0];
175                             else
176                                 leftUnionArray[index].setDConst(0.0);
177                             index++;
178                         }
179                     }
180                 } else {
181                     int count = 0;
182                     for (int i = index; i < endIndex; i++) {
183                         if (i >= instanceSize)
184                             return;
185
186                         // construct the matrix in column-major order, from
187                         // the components provided, in order
188                         leftUnionArray[i] = rightUnionArray[count];
189
190                         index++;
191                         count++;
192                     }
193                 }
194             }
195         }
196     }
197 }
198
199 bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
200 {
201     if (root == 0)
202         return false;
203
204     TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
205
206     root->traverse(&it);
207     if (it.error)
208         return true;
209     else
210         return false;
211 }
212
213 } // end namespace glslang