• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2002-2014 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 
7 #include "compiler/translator/ParseContext.h"
8 
9 //
10 // Use this class to carry along data from node to node in
11 // the traversal
12 //
13 class TConstTraverser : public TIntermTraverser
14 {
15   public:
TConstTraverser(ConstantUnion * cUnion,bool singleConstParam,TOperator constructType,TInfoSink & sink,TType & t)16     TConstTraverser(ConstantUnion *cUnion, bool singleConstParam,
17                     TOperator constructType, TInfoSink &sink, TType &t)
18         : error(false),
19           mIndex(0),
20           mUnionArray(cUnion),
21           mType(t),
22           mConstructorType(constructType),
23           mSingleConstantParam(singleConstParam),
24           mInfoSink(sink),
25           mSize(0),
26           mIsDiagonalMatrixInit(false),
27           mMatrixCols(0),
28           mMatrixRows(0)
29     {
30     }
31 
32     bool error;
33 
34   protected:
35     void visitSymbol(TIntermSymbol *);
36     void visitConstantUnion(TIntermConstantUnion *);
37     bool visitBinary(Visit visit, TIntermBinary *);
38     bool visitUnary(Visit visit, TIntermUnary *);
39     bool visitSelection(Visit visit, TIntermSelection *);
40     bool visitAggregate(Visit visit, TIntermAggregate *);
41     bool visitLoop(Visit visit, TIntermLoop *);
42     bool visitBranch(Visit visit, TIntermBranch *);
43 
44     size_t mIndex;
45     ConstantUnion *mUnionArray;
46     TType mType;
47     TOperator mConstructorType;
48     bool mSingleConstantParam;
49     TInfoSink &mInfoSink;
50     size_t mSize; // size of the constructor ( 4 for vec4)
51     bool mIsDiagonalMatrixInit;
52     int mMatrixCols; // columns of the matrix
53     int mMatrixRows; // rows of the matrix
54 };
55 
56 //
57 // The rest of the file are the traversal functions.  The last one
58 // is the one that starts the traversal.
59 //
60 // Return true from interior nodes to have the external traversal
61 // continue on to children.  If you process children yourself,
62 // return false.
63 //
visitSymbol(TIntermSymbol * node)64 void TConstTraverser::visitSymbol(TIntermSymbol *node)
65 {
66     mInfoSink.info.message(EPrefixInternalError, node->getLine(),
67                            "Symbol Node found in constant constructor");
68     return;
69 }
70 
visitBinary(Visit visit,TIntermBinary * node)71 bool TConstTraverser::visitBinary(Visit visit, TIntermBinary *node)
72 {
73     TQualifier qualifier = node->getType().getQualifier();
74 
75     if (qualifier != EvqConst)
76     {
77         TString buf;
78         buf.append("'constructor' : assigning non-constant to ");
79         buf.append(mType.getCompleteString());
80         mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
81         error = true;
82         return false;
83     }
84 
85     mInfoSink.info.message(EPrefixInternalError, node->getLine(),
86                            "Binary Node found in constant constructor");
87     return false;
88 }
89 
visitUnary(Visit visit,TIntermUnary * node)90 bool TConstTraverser::visitUnary(Visit visit, TIntermUnary *node)
91 {
92     TString buf;
93     buf.append("'constructor' : assigning non-constant to ");
94     buf.append(mType.getCompleteString());
95     mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
96     error = true;
97     return false;
98 }
99 
visitAggregate(Visit visit,TIntermAggregate * node)100 bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
101 {
102     if (!node->isConstructor() && node->getOp() != EOpComma)
103     {
104         TString buf;
105         buf.append("'constructor' : assigning non-constant to ");
106         buf.append(mType.getCompleteString());
107         mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
108         error = true;
109         return false;
110     }
111 
112     if (node->getSequence()->size() == 0)
113     {
114         error = true;
115         return false;
116     }
117 
118     bool flag = node->getSequence()->size() == 1 &&
119                 (*node->getSequence())[0]->getAsTyped()->getAsConstantUnion();
120     if (flag)
121     {
122         mSingleConstantParam = true;
123         mConstructorType = node->getOp();
124         mSize = node->getType().getObjectSize();
125 
126         if (node->getType().isMatrix())
127         {
128             mIsDiagonalMatrixInit = true;
129             mMatrixCols = node->getType().getCols();
130             mMatrixRows = node->getType().getRows();
131         }
132     }
133 
134     for (TIntermSequence::iterator p = node->getSequence()->begin();
135          p != node->getSequence()->end(); p++)
136     {
137         if (node->getOp() == EOpComma)
138             mIndex = 0;
139         (*p)->traverse(this);
140     }
141     if (flag)
142     {
143         mSingleConstantParam = false;
144         mConstructorType = EOpNull;
145         mSize = 0;
146         mIsDiagonalMatrixInit = false;
147         mMatrixCols = 0;
148         mMatrixRows = 0;
149     }
150     return false;
151 }
152 
visitSelection(Visit visit,TIntermSelection * node)153 bool TConstTraverser::visitSelection(Visit visit, TIntermSelection *node)
154 {
155     mInfoSink.info.message(EPrefixInternalError, node->getLine(),
156                            "Selection Node found in constant constructor");
157     error = true;
158     return false;
159 }
160 
visitConstantUnion(TIntermConstantUnion * node)161 void TConstTraverser::visitConstantUnion(TIntermConstantUnion *node)
162 {
163     if (!node->getUnionArrayPointer())
164     {
165         // The constant was not initialized, this should already have been logged
166         ASSERT(mInfoSink.info.size() != 0);
167         return;
168     }
169 
170     ConstantUnion *leftUnionArray = mUnionArray;
171     size_t instanceSize = mType.getObjectSize();
172     TBasicType basicType = mType.getBasicType();
173 
174     if (mIndex >= instanceSize)
175         return;
176 
177     if (!mSingleConstantParam)
178     {
179         size_t objectSize = node->getType().getObjectSize();
180         ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
181         for (size_t i=0; i < objectSize; i++)
182         {
183             if (mIndex >= instanceSize)
184                 return;
185             leftUnionArray[mIndex].cast(basicType, rightUnionArray[i]);
186             mIndex++;
187         }
188     }
189     else
190     {
191         size_t totalSize = mIndex + mSize;
192         ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
193         if (!mIsDiagonalMatrixInit)
194         {
195             int count = 0;
196             for (size_t i = mIndex; i < totalSize; i++)
197             {
198                 if (i >= instanceSize)
199                     return;
200                 leftUnionArray[i].cast(basicType, rightUnionArray[count]);
201                 mIndex++;
202                 if (node->getType().getObjectSize() > 1)
203                     count++;
204             }
205         }
206         else
207         {
208             // for matrix diagonal constructors from a single scalar
209             for (int i = 0, col = 0; col < mMatrixCols; col++)
210             {
211                 for (int row = 0; row < mMatrixRows; row++, i++)
212                 {
213                     if (col == row)
214                     {
215                         leftUnionArray[i].cast(basicType, rightUnionArray[0]);
216                     }
217                     else
218                     {
219                         leftUnionArray[i].setFConst(0.0f);
220                     }
221                     mIndex++;
222                 }
223             }
224         }
225     }
226 }
227 
visitLoop(Visit visit,TIntermLoop * node)228 bool TConstTraverser::visitLoop(Visit visit, TIntermLoop *node)
229 {
230     mInfoSink.info.message(EPrefixInternalError, node->getLine(),
231                            "Loop Node found in constant constructor");
232     error = true;
233     return false;
234 }
235 
visitBranch(Visit visit,TIntermBranch * node)236 bool TConstTraverser::visitBranch(Visit visit, TIntermBranch *node)
237 {
238     mInfoSink.info.message(EPrefixInternalError, node->getLine(),
239                            "Branch Node found in constant constructor");
240     error = true;
241     return false;
242 }
243 
244 //
245 // This function is the one to call externally to start the traversal.
246 // Individual functions can be initialized to 0 to skip processing of that
247 // type of node.  It's children will still be processed.
248 //
parseConstTree(const TSourceLoc & line,TIntermNode * root,ConstantUnion * unionArray,TOperator constructorType,TType t,bool singleConstantParam)249 bool TIntermediate::parseConstTree(
250     const TSourceLoc &line, TIntermNode *root, ConstantUnion *unionArray,
251     TOperator constructorType, TType t, bool singleConstantParam)
252 {
253     if (root == 0)
254         return false;
255 
256     TConstTraverser it(unionArray, singleConstantParam, constructorType,
257                        mInfoSink, t);
258 
259     root->traverse(&it);
260     if (it.error)
261         return true;
262     else
263         return false;
264 }
265