~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/mesa/shader/slang/MachineIndependent/parseConst.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
#include "ParseHelper.h"
36
 
 
37
 
//
38
 
// Use this class to carry along data from node to node in 
39
 
// the traversal
40
 
//
41
 
class TConstTraverser : public TIntermTraverser {
42
 
public:
43
 
    TConstTraverser(constUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) : unionArray(cUnion), type(t),
44
 
        constructorType(constructType), singleConstantParam(singleConstParam), infoSink(sink), symbolTable(symTable), error(false), isMatrix(false), matrixSize(0) {  index = 0; tOp = EOpNull;}
45
 
    int index ;
46
 
    constUnion *unionArray;
47
 
    TOperator tOp;
48
 
    TType type;
49
 
    TOperator constructorType;
50
 
    bool singleConstantParam;
51
 
    TInfoSink& infoSink;
52
 
    TSymbolTable& symbolTable;
53
 
    bool error;
54
 
    int size; // size of the constructor ( 4 for vec4)
55
 
    bool isMatrix;
56
 
    int matrixSize; // dimension of the matrix (nominal size and not the instance size)
57
 
};
58
 
 
59
 
//
60
 
// The rest of the file are the traversal functions.  The last one
61
 
// is the one that starts the traversal.
62
 
//
63
 
// Return true from interior nodes to have the external traversal
64
 
// continue on to children.  If you process children yourself,
65
 
// return false.
66
 
//
67
 
 
68
 
void ParseSymbol(TIntermSymbol* node, TIntermTraverser* it)
69
 
{
70
 
    TConstTraverser* oit = static_cast<TConstTraverser*>(it);
71
 
    TQualifier qualifier = node->getType().getQualifier();
72
 
    constUnion* unionArray = oit->unionArray;
73
 
    int instanceSize;
74
 
    if (oit->type.getBasicType() == EbtStruct)
75
 
        instanceSize = oit->type.getStructSize();
76
 
    else
77
 
        instanceSize = oit->type.getInstanceSize();
78
 
 
79
 
    if (oit->index >= instanceSize)
80
 
        return;
81
 
 
82
 
    if (qualifier != EvqConst) {
83
 
        char buf[200];
84
 
        sprintf(buf, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
85
 
        oit->infoSink.info.message(EPrefixError, buf, node->getLine());
86
 
        oit->error = true;
87
 
        return ;  
88
 
    }
89
 
    TSymbol* symbol = oit->symbolTable.find(node->getSymbol());
90
 
    TVariable* tVar = static_cast<TVariable*>(symbol);
91
 
 
92
 
    constUnion* constArray = tVar->getConstPointer();
93
 
    if (!constArray) {
94
 
        char buf[200];
95
 
        sprintf(buf, "'constructor' : constant '%s' has not been initialized correctly", node->getSymbol().c_str());
96
 
        oit->infoSink.info.message(EPrefixError, buf, node->getLine());
97
 
        oit->error = true;
98
 
        return;
99
 
    }
100
 
    int symbolSize;
101
 
 
102
 
    if (tVar->getType().getBasicType() == EbtStruct)
103
 
        symbolSize = tVar->getType().getStructSize();
104
 
    else 
105
 
        symbolSize = tVar->getType().getInstanceSize();
106
 
    
107
 
    // for constructors such as ivec4(vec4), if vec4 is a symbol node, then the appropriate conversion is required as the
108
 
    // types do not match
109
 
    for (int i = 0; i < symbolSize; i++) {
110
 
        if (oit->index >= instanceSize)
111
 
            return;
112
 
        if (tVar->getType().getBasicType() == oit->type.getBasicType() || oit->type.getBasicType() == EbtStruct)
113
 
            (unionArray[oit->index]) = constArray[i];
114
 
        else {
115
 
            switch (tVar->getType().getBasicType()) {
116
 
            case EbtFloat:
117
 
                switch (oit->type.getBasicType()) {
118
 
                case EbtInt:  unionArray[oit->index].iConst = static_cast<int> (constArray[i].fConst);  break;
119
 
                case EbtBool: unionArray[oit->index].bConst = constArray[i].fConst != 0.0; break;    
120
 
                default: oit->infoSink.info.message(EPrefixInternalError, "Incorrect type, cannot parse symbol", node->getLine()); break;
121
 
                }
122
 
                break;
123
 
            case EbtInt:
124
 
                switch (oit->type.getBasicType()) {
125
 
                case EbtFloat:  unionArray[oit->index].fConst = static_cast<float>(constArray[i].iConst);  break;
126
 
                case EbtBool: unionArray[oit->index].bConst = constArray[i].iConst != 0 ; break;    
127
 
                default: oit->infoSink.info.message(EPrefixInternalError, "Incorrect type, cannot parse symbol", node->getLine()); break;
128
 
                }
129
 
                break;
130
 
            case EbtBool:
131
 
                switch (oit->type.getBasicType()) {
132
 
                case EbtFloat:  unionArray[oit->index].fConst = static_cast<float>(constArray[i].bConst);  break;
133
 
                case EbtInt: unionArray[oit->index].iConst = static_cast<int> (constArray[i].bConst); break;    
134
 
                default: oit->infoSink.info.message(EPrefixInternalError, "Incorrect type, cannot parse symbol", node->getLine()); break;
135
 
                }
136
 
                break;
137
 
            default: oit->infoSink.info.message(EPrefixInternalError, "Incorrect type, cannot parse symbol", node->getLine()); break;
138
 
            } 
139
 
        }
140
 
    (oit->index)++;
141
 
    }
142
 
}
143
 
 
144
 
bool ParseBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
145
 
{
146
 
    TConstTraverser* oit = static_cast<TConstTraverser*>(it);
147
 
    
148
 
    TQualifier qualifier = node->getType().getQualifier();
149
 
    
150
 
    if (qualifier != EvqConst) {
151
 
        char buf[200];
152
 
        sprintf(buf, "'constructor' : assigning non-constant to %s", oit->type.getCompleteString().c_str());
153
 
        oit->infoSink.info.message(EPrefixError, buf, node->getLine());
154
 
        oit->error = true;
155
 
        return false;  
156
 
    }
157
 
 
158
 
   oit->infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine());
159
 
    
160
 
    return false;
161
 
}
162
 
 
163
 
bool ParseUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
164
 
{
165
 
    TConstTraverser* oit = static_cast<TConstTraverser*>(it);
166
 
 
167
 
    char buf[200];
168
 
    sprintf(buf, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
169
 
    oit->infoSink.info.message(EPrefixError, buf, node->getLine());
170
 
    oit->error = true;
171
 
    return false;  
172
 
}
173
 
 
174
 
bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
175
 
{
176
 
    TConstTraverser* oit = static_cast<TConstTraverser*>(it);
177
 
 
178
 
    if (!node->isConstructor() && node->getOp() != EOpComma) {
179
 
        char buf[200];
180
 
        sprintf(buf, "'constructor' : assigning non-constant to '%s'", oit->type.getCompleteString().c_str());
181
 
        oit->infoSink.info.message(EPrefixError, buf, node->getLine());
182
 
        oit->error = true;
183
 
        return false;  
184
 
    }
185
 
 
186
 
    if (node->getSequence().size() == 0) {
187
 
        oit->error = true;
188
 
        return false;
189
 
    }
190
 
 
191
 
    bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
192
 
    if (flag) 
193
 
    {
194
 
        oit->singleConstantParam = true; 
195
 
        oit->constructorType = node->getOp();
196
 
        if (node->getType().getBasicType() == EbtStruct)
197
 
            oit->size = node->getType().getStructSize();
198
 
        else
199
 
            oit->size = node->getType().getInstanceSize();
200
 
        if (node->getType().isMatrix()) {
201
 
            oit->isMatrix = true;
202
 
            oit->matrixSize = node->getType().getNominalSize();
203
 
        }
204
 
    }       
205
 
 
206
 
    for (TIntermSequence::iterator p = node->getSequence().begin(); 
207
 
                                   p != node->getSequence().end(); p++) {
208
 
 
209
 
        if (node->getOp() == EOpComma)
210
 
            oit->index = 0;           
211
 
 
212
 
        (*p)->traverse(oit);
213
 
    }   
214
 
    if (flag) 
215
 
    {
216
 
        oit->singleConstantParam = false;   
217
 
        oit->constructorType = EOpNull;
218
 
        oit->size = 0;
219
 
        oit->isMatrix = false;
220
 
        oit->matrixSize = 0;
221
 
    }
222
 
    return false;
223
 
}
224
 
 
225
 
bool ParseSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
226
 
{
227
 
    TConstTraverser* oit = static_cast<TConstTraverser*>(it);
228
 
    oit->infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine());
229
 
    oit->error = true;
230
 
    return false;
231
 
}
232
 
 
233
 
void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
234
 
{
235
 
    TConstTraverser* oit = static_cast<TConstTraverser*>(it);
236
 
    constUnion* leftUnionArray = oit->unionArray;
237
 
    int instanceSize;
238
 
    if (oit->type.getBasicType() == EbtStruct)
239
 
        instanceSize = oit->type.getStructSize();
240
 
    else
241
 
        instanceSize = oit->type.getInstanceSize();
242
 
 
243
 
    if (oit->index >= instanceSize)
244
 
        return;
245
 
 
246
 
    if (!oit->singleConstantParam) {
247
 
        int size;
248
 
        if (node->getType().getBasicType() == EbtStruct)
249
 
            size = node->getType().getStructSize();
250
 
        else
251
 
            size = node->getType().getInstanceSize();
252
 
    
253
 
        constUnion *rightUnionArray = node->getUnionArrayPointer();
254
 
        for (int i=0; i < size; i++) {
255
 
            if (oit->index >= instanceSize)
256
 
                return;
257
 
            leftUnionArray[oit->index] = rightUnionArray[i];
258
 
 
259
 
            (oit->index)++;
260
 
        }
261
 
    } else {
262
 
        int size, totalSize, matrixSize;
263
 
        bool isMatrix = false;
264
 
        size = oit->size;
265
 
        matrixSize = oit->matrixSize;
266
 
        isMatrix = oit->isMatrix;
267
 
        totalSize = oit->index + size ;
268
 
        constUnion *rightUnionArray = node->getUnionArrayPointer();
269
 
        if (!isMatrix) {
270
 
            int count = 0;
271
 
            for (int i = oit->index; i < totalSize; i++) {
272
 
                if (i >= instanceSize)
273
 
                    return;
274
 
 
275
 
                leftUnionArray[i] = rightUnionArray[count];
276
 
 
277
 
                (oit->index)++;
278
 
                if (node->getType().getBasicType() == EbtStruct && node->getType().getStructSize() > 1 ||
279
 
                    node->getType().getBasicType() != EbtStruct && node->getType().getInstanceSize() > 1)
280
 
                    count++;                
281
 
            }
282
 
        } else {  // for matrix constructors
283
 
            int count = 0;
284
 
            int index = oit->index;
285
 
            for (int i = index; i < totalSize; i++) {
286
 
                if (i >= instanceSize)
287
 
                    return;
288
 
                if (index - i == 0 || (i - index) % (matrixSize + 1) == 0 )
289
 
                    leftUnionArray[i] = rightUnionArray[count];
290
 
                else 
291
 
                    leftUnionArray[i].fConst = 0.0;
292
 
 
293
 
                (oit->index)++;
294
 
                if (node->getType().getBasicType() == EbtStruct && node->getType().getStructSize() > 1 ||
295
 
                    node->getType().getBasicType() != EbtStruct && node->getType().getInstanceSize() > 1)
296
 
                    count++;                
297
 
            }
298
 
        }
299
 
    }
300
 
}
301
 
 
302
 
bool ParseLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
303
 
{
304
 
    TConstTraverser* oit = static_cast<TConstTraverser*>(it);
305
 
    oit->infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine());
306
 
    oit->error = true;
307
 
    return false;
308
 
}
309
 
 
310
 
bool ParseBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
311
 
{
312
 
    TConstTraverser* oit = static_cast<TConstTraverser*>(it);
313
 
    oit->infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine());
314
 
    oit->error = true;
315
 
    return false;
316
 
}
317
 
 
318
 
//
319
 
// This function is the one to call externally to start the traversal.
320
 
// Individual functions can be initialized to 0 to skip processing of that
321
 
// type of node.  It's children will still be processed.
322
 
//
323
 
bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, constUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
324
 
{
325
 
    if (root == 0)
326
 
        return false;
327
 
 
328
 
    TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
329
 
    
330
 
    it.visitAggregate = ParseAggregate;
331
 
    it.visitBinary = ParseBinary;
332
 
    it.visitConstantUnion = ParseConstantUnion;
333
 
    it.visitSelection = ParseSelection;
334
 
    it.visitSymbol = ParseSymbol;
335
 
    it.visitUnary = ParseUnary;
336
 
    it.visitLoop = ParseLoop;
337
 
    it.visitBranch = ParseBranch;
338
 
 
339
 
    root->traverse(&it);
340
 
    if (it.error)
341
 
        return true;
342
 
    else
343
 
        return false;
344
 
}