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

« back to all changes in this revision

Viewing changes to src/mesa/shader/slang/MachineIndependent/ParseHelper.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
 
#include "Include/InitializeParseContext.h"
37
 
#include "osinclude.h"
38
 
#include <stdarg.h>
39
 
///////////////////////////////////////////////////////////////////////
40
 
//
41
 
// Sub- vector and matrix fields
42
 
//
43
 
////////////////////////////////////////////////////////////////////////
44
 
 
45
 
//
46
 
// Look at a '.' field selector string and change it into offsets
47
 
// for a vector.
48
 
//
49
 
bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
50
 
{
51
 
    fields.num = (int) compString.size();
52
 
    if (fields.num > 4) {
53
 
        error(line, "illegal vector field selection", compString.c_str(), "");
54
 
        return false;
55
 
    }
56
 
 
57
 
    enum {
58
 
        exyzw,
59
 
        ergba,
60
 
        estpq
61
 
    } fieldSet[4];
62
 
 
63
 
    for (int i = 0; i < fields.num; ++i) {
64
 
        switch (compString[i])  {
65
 
        case 'x': 
66
 
            fields.offsets[i] = 0;
67
 
            fieldSet[i] = exyzw;
68
 
            break;
69
 
        case 'r': 
70
 
            fields.offsets[i] = 0;
71
 
            fieldSet[i] = ergba;
72
 
            break;
73
 
        case 's':
74
 
            fields.offsets[i] = 0;
75
 
            fieldSet[i] = estpq;
76
 
            break;
77
 
        case 'y': 
78
 
            fields.offsets[i] = 1;
79
 
            fieldSet[i] = exyzw;
80
 
            break;
81
 
        case 'g': 
82
 
            fields.offsets[i] = 1;
83
 
            fieldSet[i] = ergba;
84
 
            break;
85
 
        case 't':
86
 
            fields.offsets[i] = 1;
87
 
            fieldSet[i] = estpq;
88
 
            break;
89
 
        case 'z': 
90
 
            fields.offsets[i] = 2;
91
 
            fieldSet[i] = exyzw;
92
 
            break;
93
 
        case 'b': 
94
 
            fields.offsets[i] = 2;
95
 
            fieldSet[i] = ergba;
96
 
            break;
97
 
        case 'p':
98
 
            fields.offsets[i] = 2;
99
 
            fieldSet[i] = estpq;
100
 
            break;
101
 
        
102
 
        case 'w': 
103
 
            fields.offsets[i] = 3;
104
 
            fieldSet[i] = exyzw;
105
 
            break;
106
 
        case 'a': 
107
 
            fields.offsets[i] = 3;
108
 
            fieldSet[i] = ergba;
109
 
            break;
110
 
        case 'q':
111
 
            fields.offsets[i] = 3;
112
 
            fieldSet[i] = estpq;
113
 
            break;
114
 
        default:
115
 
            error(line, "illegal vector field selection", compString.c_str(), "");
116
 
            return false;
117
 
        }
118
 
    }
119
 
 
120
 
    for (int i = 0; i < fields.num; ++i) {
121
 
        if (fields.offsets[i] >= vecSize) {
122
 
        error(line, "vector field selection out of range",  compString.c_str(), "");
123
 
        return false;
124
 
    }
125
 
 
126
 
        if (i > 0) {
127
 
            if (fieldSet[i] != fieldSet[i-1]) {
128
 
                error(line, "illegal - vector component fields not from the same set", compString.c_str(), "");
129
 
                return false;
130
 
            }
131
 
        }
132
 
    }
133
 
 
134
 
    return true;
135
 
}
136
 
 
137
 
 
138
 
//
139
 
// Look at a '.' field selector string and change it into offsets
140
 
// for a matrix.
141
 
//
142
 
bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
143
 
{
144
 
    fields.wholeRow = false;
145
 
    fields.wholeCol = false;
146
 
    fields.row = -1;
147
 
    fields.col = -1;
148
 
 
149
 
    if (compString.size() != 2) {
150
 
        error(line, "illegal length of matrix field selection", compString.c_str(), "");
151
 
        return false;
152
 
    }
153
 
 
154
 
    if (compString[0] == '_') {
155
 
        if (compString[1] < '0' || compString[1] > '3') {
156
 
            error(line, "illegal matrix field selection", compString.c_str(), "");
157
 
            return false;
158
 
        }
159
 
        fields.wholeCol = true;
160
 
        fields.col = compString[1] - '0';
161
 
    } else if (compString[1] == '_') {
162
 
        if (compString[0] < '0' || compString[0] > '3') {
163
 
            error(line, "illegal matrix field selection", compString.c_str(), "");
164
 
            return false;
165
 
        }
166
 
        fields.wholeRow = true;
167
 
        fields.row = compString[0] - '0';
168
 
    } else {
169
 
        if (compString[0] < '0' || compString[0] > '3' ||
170
 
            compString[1] < '0' || compString[1] > '3') {
171
 
            error(line, "illegal matrix field selection", compString.c_str(), "");
172
 
            return false;
173
 
        }
174
 
        fields.row = compString[0] - '0';
175
 
        fields.col = compString[1] - '0';
176
 
    }
177
 
 
178
 
    if (fields.row >= matSize || fields.col >= matSize) {
179
 
        error(line, "matrix field selection out of range", compString.c_str(), "");
180
 
        return false;
181
 
    }
182
 
 
183
 
    return true;
184
 
}
185
 
 
186
 
///////////////////////////////////////////////////////////////////////
187
 
//
188
 
// Errors
189
 
//
190
 
////////////////////////////////////////////////////////////////////////
191
 
 
192
 
//
193
 
// Track whether errors have occurred.
194
 
//
195
 
void TParseContext::recover()
196
 
{
197
 
    recoveredFromError = true;
198
 
}
199
 
 
200
 
//
201
 
// Used by flex/bison to output all syntax and parsing errors.
202
 
//
203
 
void C_DECL TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken, 
204
 
                                 const char *szExtraInfoFormat, ...)
205
 
{
206
 
    char szExtraInfo[400];
207
 
    va_list marker;
208
 
    
209
 
    va_start(marker, szExtraInfoFormat);
210
 
    
211
 
    _vsnprintf(szExtraInfo, sizeof(szExtraInfo), szExtraInfoFormat, marker);
212
 
    
213
 
    /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
214
 
    infoSink.info.prefix(EPrefixError);
215
 
    infoSink.info.location(nLine);
216
 
    infoSink.info << "'" << szToken <<  "' : " << szReason << " " << szExtraInfo << "\n";
217
 
    
218
 
    va_end(marker);
219
 
 
220
 
    ++numErrors;
221
 
}
222
 
 
223
 
//
224
 
// Same error message for all places assignments don't work.
225
 
//
226
 
void TParseContext::assignError(int line, const char* op, TString left, TString right)
227
 
{
228
 
    error(line, "", op, "cannot convert from '%s' to '%s'",
229
 
          right.c_str(), left.c_str());
230
 
}
231
 
 
232
 
//
233
 
// Same error message for all places unary operations don't work.
234
 
//
235
 
void TParseContext::unaryOpError(int line, char* op, TString operand)
236
 
{
237
 
   error(line, " wrong operand type", op, 
238
 
          "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
239
 
          op, operand.c_str());
240
 
}
241
 
 
242
 
//
243
 
// Same error message for all binary operations don't work.
244
 
//
245
 
void TParseContext::binaryOpError(int line, char* op, TString left, TString right)
246
 
{
247
 
    error(line, " wrong operand types ", op, 
248
 
            "no operation '%s' exists that takes a left-hand operand of type '%s' and "
249
 
            "a right operand of type '%s' (or there is no acceptable conversion)", 
250
 
            op, left.c_str(), right.c_str());
251
 
}
252
 
 
253
 
//
254
 
// Both test and if necessary, spit out an error, to see if the node is really
255
 
// an l-value that can be operated on this way.
256
 
//
257
 
// Returns true if the was an error.
258
 
//
259
 
bool TParseContext::lValueErrorCheck(int line, char* op, TIntermTyped* node)
260
 
{
261
 
    TIntermSymbol* symNode = node->getAsSymbolNode();
262
 
    TIntermBinary* binaryNode = node->getAsBinaryNode();
263
 
 
264
 
    if (binaryNode) {
265
 
        bool errorReturn;
266
 
 
267
 
        switch(binaryNode->getOp()) {
268
 
        case EOpIndexDirect:
269
 
        case EOpIndexIndirect:
270
 
        case EOpIndexDirectStruct:
271
 
            return lValueErrorCheck(line, op, binaryNode->getLeft());
272
 
        case EOpVectorSwizzle:
273
 
            errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
274
 
            if (!errorReturn) {
275
 
                int offset[4] = {0,0,0,0};
276
 
 
277
 
                TIntermTyped* rightNode = binaryNode->getRight();
278
 
                TIntermAggregate *aggrNode = rightNode->getAsAggregate();
279
 
                
280
 
                for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 
281
 
                                               p != aggrNode->getSequence().end(); p++) {
282
 
                    int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->iConst;
283
 
                    offset[value]++;     
284
 
                    if (offset[value] > 1) {
285
 
                        error(line, " l-value of swizzle cannot have duplicate components", op, "", "");
286
 
 
287
 
                        return true;
288
 
                    }
289
 
                }
290
 
            } 
291
 
 
292
 
            return errorReturn;
293
 
        default: 
294
 
            break;
295
 
        }
296
 
        error(line, " l-value required", op, "", "");
297
 
 
298
 
        return true;
299
 
    }
300
 
 
301
 
 
302
 
    const char* symbol = 0;
303
 
    if (symNode != 0)
304
 
        symbol = symNode->getSymbol().c_str();
305
 
 
306
 
    char* message = 0;
307
 
    switch (node->getQualifier()) {
308
 
    case EvqConst:          message = "can't modify a const";        break;
309
 
    case EvqConstReadOnly:  message = "can't modify a const";        break;
310
 
    case EvqAttribute:      message = "can't modify an attribute";   break;
311
 
    case EvqUniform:        message = "can't modify a uniform";      break;
312
 
    case EvqVaryingIn:      message = "can't modify a varying";      break;
313
 
    case EvqInput:          message = "can't modify an input";       break;
314
 
    case EvqFace:           message = "can't modify gl_FrontFace";   break;
315
 
    case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
316
 
    default:
317
 
 
318
 
        //
319
 
        // Type that can't be written to?
320
 
        //
321
 
        switch (node->getBasicType()) {
322
 
        case EbtSampler1D:
323
 
        case EbtSampler2D:
324
 
        case EbtSampler3D:
325
 
        case EbtSamplerCube:
326
 
        case EbtSampler1DShadow:
327
 
        case EbtSampler2DShadow:
328
 
            message = "can't modify a sampler";
329
 
            break;
330
 
        case EbtVoid:
331
 
            message = "can't modify void";
332
 
            break;
333
 
        default: 
334
 
            break;
335
 
        }
336
 
    }
337
 
 
338
 
    if (message == 0 && binaryNode == 0 && symNode == 0) {
339
 
        error(line, " l-value required", op, "", "");
340
 
 
341
 
        return true;
342
 
    }
343
 
 
344
 
 
345
 
    //
346
 
    // Everything else is okay, no error.
347
 
    //
348
 
    if (message == 0)
349
 
        return false;
350
 
 
351
 
    //
352
 
    // If we get here, we have an error and a message.
353
 
    //
354
 
    if (symNode)
355
 
        error(line, " l-value required", op, "\"%s\" (%s)", symbol, message);
356
 
    else
357
 
        error(line, " l-value required", op, "(%s)", message);
358
 
 
359
 
    return true;
360
 
}
361
 
 
362
 
//
363
 
// Both test, and if necessary spit out an error, to see if the node is really
364
 
// a constant.
365
 
//
366
 
// Returns true if the was an error.
367
 
//
368
 
bool TParseContext::constErrorCheck(TIntermTyped* node)
369
 
{
370
 
    if (node->getQualifier() == EvqConst)
371
 
        return false;
372
 
 
373
 
    error(node->getLine(), "constant expression required", "", "");
374
 
 
375
 
    return true;
376
 
}
377
 
 
378
 
//
379
 
// Both test, and if necessary spit out an error, to see if the node is really
380
 
// an integer.
381
 
//
382
 
// Returns true if the was an error.
383
 
//
384
 
bool TParseContext::integerErrorCheck(TIntermTyped* node, char* token)
385
 
{
386
 
    if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
387
 
        return false;
388
 
 
389
 
    error(node->getLine(), "integer expression required", token, "");
390
 
 
391
 
    return true;
392
 
}
393
 
 
394
 
//
395
 
// Both test, and if necessary spit out an error, to see if we are currently
396
 
// globally scoped.
397
 
//
398
 
// Returns true if the was an error.
399
 
//
400
 
bool TParseContext::globalErrorCheck(int line, bool global, char* token)
401
 
{
402
 
    if (global)
403
 
        return false;
404
 
 
405
 
    error(line, "only allowed at global scope", token, "");
406
 
 
407
 
    return true;
408
 
}
409
 
 
410
 
//
411
 
// For now, keep it simple:  if it starts "gl_", it's reserved, independent
412
 
// of scope.  Except, if the symbol table is at the built-in push-level,
413
 
// which is when we are parsing built-ins.
414
 
//
415
 
// Returns true if there was an error.
416
 
//
417
 
bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
418
 
{
419
 
    if (symbolTable.atBuiltInLevel() ||
420
 
        identifier.substr(0, 3) != TString("gl_"))
421
 
        return false;
422
 
 
423
 
    error(line, "reserved built-in name", "gl_", "");
424
 
 
425
 
    return true;        
426
 
}
427
 
 
428
 
//
429
 
// Make sure there is enough data provided to the constructor to build
430
 
// something of the type of the constructor.  Also returns the type of
431
 
// the constructor.
432
 
//
433
 
// Returns true if there was an error in construction.
434
 
//
435
 
bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
436
 
{
437
 
    switch(op) {
438
 
    case EOpConstructInt:     *type = TType(EbtInt);                               break;
439
 
    case EOpConstructBool:    *type = TType(EbtBool);                              break;
440
 
    case EOpConstructFloat:   *type = TType(EbtFloat);                             break;
441
 
    case EOpConstructVec2:    *type = TType(EbtFloat, EvqTemporary, 2);            break;
442
 
    case EOpConstructVec3:    *type = TType(EbtFloat, EvqTemporary, 3);            break;
443
 
    case EOpConstructVec4:    *type = TType(EbtFloat, EvqTemporary, 4);            break;
444
 
    case EOpConstructBVec2:   *type = TType(EbtBool,  EvqTemporary, 2);            break;
445
 
    case EOpConstructBVec3:   *type = TType(EbtBool,  EvqTemporary, 3);            break;
446
 
    case EOpConstructBVec4:   *type = TType(EbtBool,  EvqTemporary, 4);            break;
447
 
    case EOpConstructIVec2:   *type = TType(EbtInt,   EvqTemporary, 2);            break;
448
 
    case EOpConstructIVec3:   *type = TType(EbtInt,   EvqTemporary, 3);            break;
449
 
    case EOpConstructIVec4:   *type = TType(EbtInt,   EvqTemporary, 4);            break;
450
 
    case EOpConstructMat2:    *type = TType(EbtFloat, EvqTemporary, 2, true);      break;
451
 
    case EOpConstructMat3:    *type = TType(EbtFloat, EvqTemporary, 3, true);      break;
452
 
    case EOpConstructMat4:    *type = TType(EbtFloat, EvqTemporary, 4, true);      break;
453
 
    case EOpConstructStruct:  *type = TType(function.getReturnType().getStruct(), function.getReturnType().getTypeName()); break;
454
 
    default:
455
 
        error(line, "expected constructor", "Internal Error", "");
456
 
        return true;
457
 
    }
458
 
 
459
 
    bool constructingMatrix = false;
460
 
    switch(op) {
461
 
    case EOpConstructMat2:
462
 
    case EOpConstructMat3:
463
 
    case EOpConstructMat4:
464
 
        constructingMatrix = true;
465
 
        break;
466
 
    default: 
467
 
        break;
468
 
    }
469
 
 
470
 
    //
471
 
    // Note: It's okay to have too many components available, but not okay to have unused
472
 
    // arguments.  'full' will go to true when enough args have been seen.  If we loop
473
 
    // again, there is an extra argument, so 'overfull' will become true.
474
 
    //
475
 
 
476
 
    int size = 0;
477
 
    bool constType = true;
478
 
    bool full = false;
479
 
    bool overFull = false;
480
 
    bool matrixInMatrix = false;
481
 
    for (int i = 0; i < function.getParamCount(); ++i) {
482
 
        size += function[i].type->getInstanceSize();
483
 
        if (constructingMatrix && function[i].type->isMatrix())
484
 
            matrixInMatrix = true;
485
 
        if (full)
486
 
            overFull = true;
487
 
        if (op != EOpConstructStruct && size >= type->getInstanceSize())
488
 
            full = true;
489
 
        if (function[i].type->getQualifier() != EvqConst)
490
 
            constType = false;
491
 
    }
492
 
    
493
 
    if (constType)
494
 
        type->changeQualifier(EvqConst);
495
 
 
496
 
    if (matrixInMatrix) {
497
 
        error(line, "constructing matrix from matrix", "constructor", "(reserved)");
498
 
        return true;
499
 
    }
500
 
 
501
 
    if (overFull) {
502
 
        error(line, "too many arguments", "constructor", "");
503
 
        return true;
504
 
    }
505
 
 
506
 
    if (size != 1 && size < type->getInstanceSize() || (size < 1) && op == EOpConstructStruct) {
507
 
        error(line, "not enough data provided for construction", "constructor", "");
508
 
        return true;
509
 
    }
510
 
 
511
 
    TIntermTyped* typed = node->getAsTyped();
512
 
    if (typed == 0) {
513
 
        error(line, "constructor argument does not have a type", "constructor", "");
514
 
        return true;
515
 
    }
516
 
    if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
517
 
        error(line, "cannot convert a sampler", "constructor", "");
518
 
        return true;
519
 
    }
520
 
    if (typed->getBasicType() == EbtVoid) {
521
 
        error(line, "cannot convert a void", "constructor", "");
522
 
        return true;
523
 
    }
524
 
 
525
 
    return false;
526
 
}
527
 
 
528
 
// This function checks to see if a void variable has been declared and raise an error message for such a case
529
 
//
530
 
// returns true in case of an error
531
 
//
532
 
bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
533
 
{
534
 
    if (pubType.type == EbtVoid) {
535
 
        error(line, "illegal use of type 'void'", identifier.c_str(), "");
536
 
        return true;
537
 
    } 
538
 
 
539
 
    return false;
540
 
}
541
 
 
542
 
// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
543
 
//
544
 
// returns true in case of an error
545
 
//
546
 
bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
547
 
{
548
 
    if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
549
 
        error(line, "boolean expression expected", "", "");
550
 
        return true;
551
 
    } 
552
 
 
553
 
    return false;
554
 
}
555
 
 
556
 
// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
557
 
//
558
 
// returns true in case of an error
559
 
//
560
 
bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
561
 
{
562
 
    if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
563
 
        error(line, "boolean expression expected", "", "");
564
 
        return true;
565
 
    } 
566
 
 
567
 
    return false;
568
 
}
569
 
 
570
 
bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
571
 
{
572
 
    if (pType.type == EbtStruct) {
573
 
        if (containsSampler(*pType.userDef)) {
574
 
            error(line, reason, TType::getBasicString(pType.type), "(structure contains a sampler)");
575
 
        
576
 
            return true;
577
 
        }
578
 
        
579
 
        return false;
580
 
    } else if (IsSampler(pType.type)) {
581
 
        error(line, reason, TType::getBasicString(pType.type), "");
582
 
 
583
 
        return true;
584
 
    }
585
 
 
586
 
    return false;
587
 
}
588
 
 
589
 
bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
590
 
{
591
 
    if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
592
 
        pType.type == EbtStruct) {
593
 
        error(line, "cannot be used with a structure", getQualifierString(pType.qualifier), "");
594
 
        
595
 
        return true;
596
 
    }
597
 
 
598
 
    if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
599
 
        return true;
600
 
 
601
 
    return false;
602
 
}
603
 
 
604
 
bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
605
 
{
606
 
    if ((qualifier == EvqOut || qualifier == EvqInOut) && 
607
 
             type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
608
 
        error(line, "samplers cannot be output parameters", type.getBasicString(), "");
609
 
        return true;
610
 
    }
611
 
 
612
 
    return false;
613
 
}
614
 
 
615
 
bool TParseContext::containsSampler(TType& type)
616
 
{
617
 
    if (IsSampler(type.getBasicType()))
618
 
        return true;
619
 
 
620
 
    if (type.getBasicType() == EbtStruct) {
621
 
        TTypeList& structure = *type.getStruct();
622
 
        for (unsigned int i = 0; i < structure.size(); ++i) {
623
 
            if (containsSampler(*structure[i].type))
624
 
                return true;
625
 
        }
626
 
    }
627
 
 
628
 
    return false;
629
 
}
630
 
 
631
 
bool TParseContext::insertBuiltInArrayAtGlobalLevel()
632
 
{
633
 
    TString *name = NewPoolTString("gl_TexCoord");
634
 
    TSymbol* symbol = symbolTable.find(*name);
635
 
    if (!symbol) {
636
 
        error(0, "INTERNAL ERROR finding symbol", name->c_str(), "");
637
 
        return true;
638
 
    }
639
 
    TVariable* variable = static_cast<TVariable*>(symbol);
640
 
 
641
 
    TVariable* newVariable = new TVariable(name, variable->getType());
642
 
 
643
 
    if (! symbolTable.insert(*newVariable)) {
644
 
        delete newVariable;
645
 
        error(0, "INTERNAL ERROR inserting new symbol", name->c_str(), "");
646
 
        return true;
647
 
    }
648
 
 
649
 
    return false;
650
 
}
651
 
 
652
 
//
653
 
// Do all the semantic checking for declaring an array, with and 
654
 
// without a size, and make the right changes to the symbol table.
655
 
//
656
 
// size == 0 means no specified size.
657
 
//
658
 
// Returns true if there was an error.
659
 
//
660
 
bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TIntermTyped* size)
661
 
{
662
 
    //
663
 
    // Don't check for reserved word use until after we know it's not in the symbol table,
664
 
    // because reserved arrays can be redeclared.
665
 
    //
666
 
 
667
 
    //
668
 
    // Can the type be an array?
669
 
    //
670
 
    if (type.array || type.qualifier == EvqAttribute || type.qualifier == EvqConst) {
671
 
        error(line, "cannot declare arrays of this type", TType(type).getCompleteString().c_str(), "");
672
 
        return true;
673
 
    }
674
 
    type.array = true;
675
 
 
676
 
    //
677
 
    // size will be 0 if there is no size declared, otherwise it contains the size
678
 
    // declared.
679
 
    //
680
 
    TIntermConstantUnion* constant = 0;
681
 
    if (size) {
682
 
        constant = size->getAsConstantUnion();
683
 
        if (constant == 0 || constant->getBasicType() != EbtInt || constant->getUnionArrayPointer()->iConst <= 0) {
684
 
            error(line, "array size must be a positive integer", identifier.c_str(), "");
685
 
            return true;
686
 
        }
687
 
    }
688
 
 
689
 
    bool builtIn = false; 
690
 
    bool sameScope = false;
691
 
    TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
692
 
    if (symbol == 0 || !sameScope) {
693
 
        if (reservedErrorCheck(line, identifier))
694
 
            return true;
695
 
        
696
 
        TVariable* variable = new TVariable(&identifier, TType(type));
697
 
 
698
 
        if (size)
699
 
            variable->getType().setArraySize(constant->getUnionArrayPointer()->iConst);
700
 
 
701
 
        if (! symbolTable.insert(*variable)) {
702
 
            delete variable;
703
 
            error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
704
 
            return true;
705
 
        }
706
 
    } else {
707
 
        if (! symbol->isVariable()) {
708
 
            error(line, "variable expected", identifier.c_str(), "");
709
 
            return true;
710
 
        }
711
 
 
712
 
        TVariable* variable = static_cast<TVariable*>(symbol);
713
 
        if (! variable->getType().isArray()) {
714
 
            error(line, "redeclaring non-array as array", identifier.c_str(), "");
715
 
            return true;
716
 
        }
717
 
        if (variable->getType().getArraySize() > 0) {
718
 
            error(line, "redeclaration of array with size", identifier.c_str(), "");
719
 
            return true;
720
 
        }
721
 
        
722
 
        if (variable->getType() != TType(type)) {
723
 
            error(line, "redeclaration of array with a different type", identifier.c_str(), "");
724
 
            return true;
725
 
        }
726
 
 
727
 
        TType* t = variable->getArrayInformationType();
728
 
        while (t != 0) {
729
 
            if (t->getMaxArraySize() > constant->getUnionArrayPointer()->iConst) {
730
 
                error(line, "higher index value already used for the array", identifier.c_str(), "");
731
 
                return true;
732
 
            }
733
 
            t->setArraySize(constant->getUnionArrayPointer()->iConst);
734
 
            t = t->getArrayInformationType();
735
 
        }
736
 
 
737
 
        if (size)
738
 
            variable->getType().setArraySize(constant->getUnionArrayPointer()->iConst);
739
 
    } 
740
 
 
741
 
    if (voidErrorCheck(line, identifier, type))
742
 
        return true;
743
 
 
744
 
    return false;
745
 
}
746
 
 
747
 
bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
748
 
{
749
 
    bool builtIn = false;
750
 
    TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
751
 
    if (symbol == 0) {
752
 
        error(line, " undeclared identifier", node->getSymbol().c_str(), "");
753
 
        return true;
754
 
    }
755
 
    TVariable* variable = static_cast<TVariable*>(symbol);
756
 
 
757
 
    type->setArrayInformationType(variable->getArrayInformationType());
758
 
    variable->updateArrayInformationType(type);
759
 
 
760
 
    // we dont want to update the maxArraySize when this flag is not set, we just want to include this 
761
 
    // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
762
 
    if (!updateFlag)
763
 
        return false;
764
 
 
765
 
    size++;
766
 
    variable->getType().setMaxArraySize(size);
767
 
    type->setMaxArraySize(size);
768
 
    TType* tt = type;
769
 
 
770
 
    while(tt->getArrayInformationType() != 0) {
771
 
        tt = tt->getArrayInformationType();
772
 
        tt->setMaxArraySize(size);
773
 
    }
774
 
 
775
 
    return false;
776
 
}
777
 
 
778
 
//
779
 
// Do semantic checking for a variable declaration that has no initializer,
780
 
// and update the symbol table.
781
 
//
782
 
// Returns true if there was an error.
783
 
//
784
 
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
785
 
{
786
 
    if (reservedErrorCheck(line, identifier))
787
 
        recover();
788
 
 
789
 
    //
790
 
    // Make the qualifier make sense, error is issued in a little bit.
791
 
    //
792
 
    bool constError = false;
793
 
    if (type.qualifier == EvqConst) {
794
 
        type.qualifier = EvqTemporary;
795
 
        constError = true;
796
 
    }
797
 
 
798
 
    TVariable* variable = new TVariable(&identifier, TType(type));
799
 
 
800
 
    if (! symbolTable.insert(*variable)) {
801
 
        error(line, "redefinition", variable->getName().c_str(), "");
802
 
        delete variable;
803
 
        return true;
804
 
    }
805
 
    if (constError) {
806
 
        error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
807
 
        return true;
808
 
    }
809
 
 
810
 
    if (voidErrorCheck(line, identifier, type))
811
 
        return true;
812
 
 
813
 
    return false;
814
 
}
815
 
 
816
 
bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
817
 
{    
818
 
    if (qualifier != EvqConst && qualifier != EvqTemporary) {
819
 
        error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), "");
820
 
        return true;
821
 
    }
822
 
    if (qualifier == EvqConst && paramQualifier != EvqIn) {
823
 
        error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
824
 
        return true;
825
 
    }
826
 
 
827
 
    if (qualifier == EvqConst)
828
 
        type->changeQualifier(EvqConstReadOnly);
829
 
    else
830
 
        type->changeQualifier(paramQualifier);
831
 
 
832
 
    return false;
833
 
}
834
 
 
835
 
/////////////////////////////////////////////////////////////////////////////////
836
 
//
837
 
// Non-Errors.
838
 
//
839
 
/////////////////////////////////////////////////////////////////////////////////
840
 
 
841
 
//
842
 
// Look up a function name in the symbol table, and make sure it is a function.
843
 
//
844
 
// Return the function symbol if found, otherwise 0.
845
 
//
846
 
const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
847
 
{
848
 
    const TSymbol* symbol = symbolTable.find(call->getMangledName(), builtIn);
849
 
 
850
 
    if (symbol == 0) {        
851
 
        error(line, "no matching overloaded function found", call->getName().c_str(), "");
852
 
        return 0;
853
 
    }
854
 
 
855
 
    if (! symbol->isFunction()) {
856
 
        error(line, "function name expected", call->getName().c_str(), "");
857
 
        return 0;
858
 
    }
859
 
    
860
 
    const TFunction* function = static_cast<const TFunction*>(symbol);
861
 
    
862
 
    return function;
863
 
}
864
 
//
865
 
// Initializers show up in several places in the grammar.  Have one set of
866
 
// code to handle them here.
867
 
//
868
 
bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, 
869
 
                                       TIntermTyped* initializer, TIntermNode*& intermNode)
870
 
{
871
 
    if (reservedErrorCheck(line, identifier))
872
 
        return true;
873
 
 
874
 
    if (voidErrorCheck(line, identifier, pType))
875
 
        return true;
876
 
 
877
 
    //
878
 
    // add variable to symbol table
879
 
    //
880
 
    TVariable* variable = new TVariable(&identifier, TType(pType));
881
 
    if (! symbolTable.insert(*variable)) {
882
 
        error(line, "redefinition", variable->getName().c_str(), "");
883
 
        return true;
884
 
        // don't delete variable, it's used by error recovery, and the pool 
885
 
        // pop will take care of the memory
886
 
    }
887
 
 
888
 
    //
889
 
    // identifier must be of type constant, a global, or a temporary
890
 
    //
891
 
    TQualifier qualifier = variable->getType().getQualifier();
892
 
    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
893
 
        error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString(), "");
894
 
        return true;
895
 
    }
896
 
    //
897
 
    // test for and propagate constant
898
 
    //
899
 
 
900
 
    if (qualifier == EvqConst) {
901
 
        if (qualifier != initializer->getType().getQualifier()) {
902
 
            error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
903
 
            variable->getType().changeQualifier(EvqTemporary);
904
 
            return true;
905
 
        }
906
 
        if (TType(pType) != initializer->getType()) {
907
 
            error(line, " non-matching types for const initializer ", 
908
 
                variable->getType().getQualifierString(), "");
909
 
            variable->getType().changeQualifier(EvqTemporary);
910
 
            return true;
911
 
        }
912
 
        if (initializer->getAsConstantUnion()) { 
913
 
            constUnion* unionArray = variable->getConstPointer();            
914
 
 
915
 
            if (pType.size == 1 && TType(pType).getBasicType() != EbtStruct) {
916
 
                switch (pType.type ) {
917
 
                case EbtInt:
918
 
                    unionArray->iConst = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0].iConst;
919
 
                    break;
920
 
                case EbtFloat:
921
 
                    unionArray->fConst = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0].fConst;
922
 
                    break;
923
 
                case EbtBool:
924
 
                    unionArray->bConst = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0].bConst;
925
 
                    break;
926
 
                default:
927
 
                    error(line, " cannot initialize constant of this type", "", "");
928
 
                    return true;
929
 
                }
930
 
            } else {
931
 
                variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
932
 
            }
933
 
        } else if (initializer->getAsAggregate()) {
934
 
            bool returnVal = false;
935
 
            constUnion* unionArray = variable->getConstPointer();
936
 
            if (initializer->getAsAggregate()->getSequence().size() == 1 && initializer->getAsAggregate()->getSequence()[0]->getAsTyped()->getAsConstantUnion())  {
937
 
                returnVal = intermediate.parseConstTree(line, initializer, unionArray, initializer->getAsAggregate()->getOp(), symbolTable,  variable->getType(), true);
938
 
            }
939
 
            else {
940
 
                returnVal = intermediate.parseConstTree(line, initializer, unionArray, initializer->getAsAggregate()->getOp(), symbolTable, variable->getType());
941
 
            }
942
 
            intermNode = 0;
943
 
            constUnion *arrayUnion = unionArray;
944
 
            if (returnVal) {
945
 
                arrayUnion = 0;
946
 
                variable->getType().changeQualifier(EvqTemporary);
947
 
            } 
948
 
            return returnVal;
949
 
        } else if (initializer->getAsSymbolNode()) {
950
 
            const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
951
 
            const TVariable* tVar = static_cast<const TVariable*>(symbol);
952
 
 
953
 
            constUnion* constArray = tVar->getConstPointer();
954
 
            variable->shareConstPointer(constArray);
955
 
        } else {
956
 
            error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
957
 
            variable->getType().changeQualifier(EvqTemporary);
958
 
            return true;
959
 
        }
960
 
    }
961
 
 
962
 
    if (qualifier != EvqConst) {
963
 
        TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
964
 
        intermNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, line);
965
 
        if (intermNode == 0) {
966
 
            assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
967
 
            return true;
968
 
        }
969
 
    } else 
970
 
        intermNode = 0;
971
 
 
972
 
    return false;
973
 
}
974
 
 
975
 
//
976
 
// This method checks to see if the given aggregate node has all its children nodes as constants
977
 
// This method does not test if structure members are constant
978
 
//
979
 
bool TParseContext::canNodeBeRemoved(TIntermNode* childNode)
980
 
{
981
 
    TIntermAggregate *aggrNode = childNode->getAsAggregate();
982
 
    if (!aggrNode)
983
 
        return false;
984
 
 
985
 
    if (!aggrNode->isConstructor() || aggrNode->getOp() == EOpConstructStruct)
986
 
        return false;
987
 
 
988
 
    bool allConstant = true;
989
 
 
990
 
    // check if all the child nodes are constants so that they can be inserted into 
991
 
    // the parent node
992
 
    if (aggrNode) {
993
 
        TIntermSequence &childSequenceVector = aggrNode->getSequence() ;
994
 
        for (TIntermSequence::iterator p = childSequenceVector.begin(); 
995
 
                                    p != childSequenceVector.end(); p++) {
996
 
            if (!(*p)->getAsTyped()->getAsConstantUnion())
997
 
                return false;
998
 
        }
999
 
    }
1000
 
 
1001
 
    return allConstant;
1002
 
}
1003
 
 
1004
 
// This function is used to test for the correctness of the parameters passed to various constructor functions
1005
 
// and also convert them to the right datatype if it is allowed and required. 
1006
 
//
1007
 
// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
1008
 
//
1009
 
TIntermTyped* TParseContext::addConstructor(TIntermNode* node, TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
1010
 
{
1011
 
    if (node == 0)
1012
 
        return 0;
1013
 
 
1014
 
    TIntermAggregate* aggrNode = node->getAsAggregate();
1015
 
    
1016
 
    TTypeList::iterator list;
1017
 
    TTypeList* structure = 0;  // Store the information (vector) about the return type of the structure.
1018
 
    if (op == EOpConstructStruct) {
1019
 
        const TType& ttype = fnCall->getReturnType();
1020
 
        structure = ttype.getStruct();
1021
 
        list = (*structure).begin();
1022
 
    }
1023
 
 
1024
 
    bool singleArg;
1025
 
    if (aggrNode) {
1026
 
        if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
1027
 
            singleArg = true;
1028
 
        else
1029
 
            singleArg = false;
1030
 
    } else
1031
 
        singleArg = true;
1032
 
 
1033
 
    TIntermTyped *newNode;
1034
 
    if (singleArg) {
1035
 
        if (op == EOpConstructStruct) { 
1036
 
            // If structure constructor is being called for only one parameter inside the structure,
1037
 
            // we need to call constructStruct function once.
1038
 
            if (structure->size() != 1) {
1039
 
                error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
1040
 
                
1041
 
                return 0;
1042
 
            } else
1043
 
                return constructStruct(node, (*list).type, 1, node->getLine(), false);
1044
 
        } else {
1045
 
            newNode =  constructBuiltIn(type, op, node, node->getLine(), false);
1046
 
            if (newNode && newNode->getAsAggregate()) {
1047
 
                if (canNodeBeRemoved(newNode->getAsAggregate()->getSequence()[0])) {
1048
 
                    TIntermAggregate* returnAggNode = newNode->getAsAggregate()->getSequence()[0]->getAsAggregate();
1049
 
                    newNode = intermediate.removeChildNode(newNode, type, returnAggNode);
1050
 
                }
1051
 
            }
1052
 
            return newNode;
1053
 
        }
1054
 
    }
1055
 
    
1056
 
    //
1057
 
    // Handle list of arguments.
1058
 
    //
1059
 
    TIntermSequence &sequenceVector = aggrNode->getSequence() ;    // Stores the information about the parameter to the constructor
1060
 
    // if the structure constructor contains more than one parameter, then construct
1061
 
    // each parameter
1062
 
    if (op == EOpConstructStruct) {
1063
 
        if (structure->size() != sequenceVector.size()) { // If the number of parameters to the constructor does not match the expected number of parameters
1064
 
            error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
1065
 
            
1066
 
            return 0;
1067
 
        }
1068
 
    }
1069
 
    
1070
 
    int paramCount = 0;  // keeps a track of the constructor parameter number being checked    
1071
 
    
1072
 
    // for each parameter to the constructor call, check to see if the right type is passed or convert them 
1073
 
    // to the right type if possible (and allowed).
1074
 
    // for structure constructors, just check if the right type is passed, no conversion is allowed.
1075
 
    
1076
 
    for (TIntermSequence::iterator p = sequenceVector.begin(); 
1077
 
                                   p != sequenceVector.end(); p++, paramCount++) {
1078
 
        bool move = false;
1079
 
        if (op == EOpConstructStruct) {
1080
 
            newNode = constructStruct(*p, (list[paramCount]).type, paramCount+1, node->getLine(), true);
1081
 
            if (newNode)
1082
 
                move = true;
1083
 
        } else {
1084
 
            newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
1085
 
 
1086
 
            if (newNode) {
1087
 
                if (canNodeBeRemoved(newNode))
1088
 
                    intermediate.removeChildNode(sequenceVector, *type, paramCount, p, newNode->getAsAggregate());
1089
 
                else
1090
 
                    move = true;    
1091
 
            } 
1092
 
        }
1093
 
        if (move) {
1094
 
            sequenceVector.erase(p); 
1095
 
            sequenceVector.insert(p, newNode);
1096
 
        }
1097
 
    }
1098
 
 
1099
 
    return intermediate.setAggregateOperator(aggrNode, op, line);
1100
 
}
1101
 
 
1102
 
// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
1103
 
// for the parameter to the constructor (passed to this function). Essentially, it converts
1104
 
// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 
1105
 
// float, then float is converted to int.
1106
 
//
1107
 
// Returns 0 for an error or the constructed node.
1108
 
//
1109
 
TIntermTyped* TParseContext::constructBuiltIn(TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
1110
 
{
1111
 
    TIntermTyped* newNode;
1112
 
    TOperator basicOp;
1113
 
 
1114
 
    //
1115
 
    // First, convert types as needed.
1116
 
    //
1117
 
    switch (op) {
1118
 
    case EOpConstructVec2:
1119
 
    case EOpConstructVec3:
1120
 
    case EOpConstructVec4:
1121
 
    case EOpConstructMat2:
1122
 
    case EOpConstructMat3:
1123
 
    case EOpConstructMat4:
1124
 
    case EOpConstructFloat:
1125
 
        basicOp = EOpConstructFloat;
1126
 
        break;
1127
 
 
1128
 
    case EOpConstructIVec2:
1129
 
    case EOpConstructIVec3:
1130
 
    case EOpConstructIVec4:
1131
 
    case EOpConstructInt:
1132
 
        basicOp = EOpConstructInt;
1133
 
        break;
1134
 
 
1135
 
    case EOpConstructBVec2:
1136
 
    case EOpConstructBVec3:
1137
 
    case EOpConstructBVec4:
1138
 
    case EOpConstructBool:
1139
 
        basicOp = EOpConstructBool;
1140
 
        break;
1141
 
 
1142
 
    default:
1143
 
        error(line, "unsupported construction", "", "");
1144
 
        recover();
1145
 
 
1146
 
        return 0;
1147
 
    }
1148
 
    newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
1149
 
    if (newNode == 0) {
1150
 
        error(line, "can't convert", "constructor", "");
1151
 
        return 0;
1152
 
    }
1153
 
 
1154
 
    //
1155
 
    // Now, if there still isn't an operation to do the construction, and we need one, add one.
1156
 
    //
1157
 
    
1158
 
    // Otherwise, skip out early.
1159
 
    if (subset || newNode != node && newNode->getType() == *type)
1160
 
        return newNode;
1161
 
 
1162
 
    // setAggregateOperator will insert a new node for the constructor, as needed.
1163
 
    return intermediate.setAggregateOperator(newNode, op, line);
1164
 
}
1165
 
 
1166
 
// This function tests for the type of the parameters to the structures constructors. Raises
1167
 
// an error message if the expected type does not match the parameter passed to the constructor.
1168
 
//
1169
 
// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
1170
 
//
1171
 
TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
1172
 
{
1173
 
    if (*type == node->getAsTyped()->getType()) {
1174
 
        if (subset)
1175
 
            return node->getAsTyped();
1176
 
        else
1177
 
            return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
1178
 
    } else {
1179
 
        error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
1180
 
                node->getAsTyped()->getType().getBasicString(), type->getBasicString());
1181
 
        recover();
1182
 
    }
1183
 
 
1184
 
    return 0;
1185
 
}
1186
 
 
1187
 
//
1188
 
// This function returns the tree representation for the vector field(s) being accessed from contant vector.
1189
 
// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
1190
 
// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
1191
 
// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
1192
 
// a constant matrix.
1193
 
//
1194
 
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
1195
 
{
1196
 
    TIntermTyped* typedNode;
1197
 
    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1198
 
    TIntermAggregate* aggregateNode = node->getAsAggregate();
1199
 
 
1200
 
    constUnion *unionArray;
1201
 
    if (tempConstantNode) {
1202
 
        unionArray = tempConstantNode->getUnionArrayPointer();
1203
 
 
1204
 
        if (!unionArray) {  // this error message should never be raised
1205
 
            infoSink.info.message(EPrefixInternalError, "constUnion not initialized in addConstVectorNode function", line);
1206
 
            recover();
1207
 
 
1208
 
            return node;
1209
 
        }
1210
 
    } else if (aggregateNode) { // if an aggregate node is present, the value has to be taken from the parse tree 
1211
 
        // for a case like vec(4).xz
1212
 
        unionArray = new constUnion[aggregateNode->getType().getInstanceSize()];                        
1213
 
    
1214
 
        bool returnVal = false;
1215
 
        if (aggregateNode->getAsAggregate()->getSequence().size() == 1 && aggregateNode->getAsAggregate()->getSequence()[0]->getAsTyped()->getAsConstantUnion())  {
1216
 
            returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable,  aggregateNode->getType(), true);
1217
 
        }
1218
 
        else {
1219
 
            returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType());
1220
 
        }
1221
 
 
1222
 
        if (returnVal)
1223
 
            return 0;
1224
 
 
1225
 
    } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
1226
 
        error(line, "No aggregate or constant union node available", "Internal Error", "");
1227
 
        recover();
1228
 
 
1229
 
        return 0;
1230
 
    }
1231
 
 
1232
 
    constUnion* constArray = new constUnion[fields.num];
1233
 
 
1234
 
    for (int i = 0; i < fields.num; i++) {
1235
 
        if (fields.offsets[i] >= node->getType().getInstanceSize()) {
1236
 
            error(line, "", "[", "vector field selection out of range '%d'", fields.offsets[i]);
1237
 
            recover();
1238
 
            fields.offsets[i] = 0;
1239
 
        }
1240
 
        
1241
 
        constArray[i] = unionArray[fields.offsets[i]];
1242
 
 
1243
 
    } 
1244
 
    typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
1245
 
    return typedNode;
1246
 
}
1247
 
 
1248
 
//
1249
 
// This function returns the column being accessed from a constant matrix. The values are retrieved from
1250
 
// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 
1251
 
// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 
1252
 
// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
1253
 
//
1254
 
TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
1255
 
{
1256
 
    TIntermTyped* typedNode;
1257
 
    TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1258
 
    TIntermAggregate* aggregateNode = node->getAsAggregate();
1259
 
 
1260
 
    if (index >= node->getType().getNominalSize()) {
1261
 
        error(line, "", "[", "matrix field selection out of range '%d'", index);
1262
 
        recover();
1263
 
        index = 0;
1264
 
    }
1265
 
 
1266
 
    if (tempConstantNode) {
1267
 
         constUnion* unionArray = tempConstantNode->getUnionArrayPointer();
1268
 
         int size = tempConstantNode->getType().getNominalSize();
1269
 
         typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
1270
 
    } else if (aggregateNode) {
1271
 
        // for a case like mat4(5)[0]
1272
 
        constUnion* unionArray = new constUnion[aggregateNode->getType().getInstanceSize()];                        
1273
 
        int size = aggregateNode->getType().getNominalSize();
1274
 
    
1275
 
        bool returnVal = false;
1276
 
        if (aggregateNode->getAsAggregate()->getSequence().size() == 1 && aggregateNode->getAsAggregate()->getSequence()[0]->getAsTyped()->getAsConstantUnion())  {
1277
 
            returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable,  aggregateNode->getType(), true);
1278
 
        }
1279
 
        else {
1280
 
            returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType());
1281
 
        }
1282
 
 
1283
 
        if (!returnVal)
1284
 
            typedNode = intermediate.addConstantUnion(&unionArray[size*index], aggregateNode->getType(), line);
1285
 
        else 
1286
 
            return 0;
1287
 
 
1288
 
    } else {
1289
 
        error(line, "No Aggregate or Constant Union node available", "Internal Error", "");
1290
 
        recover();
1291
 
 
1292
 
        return 0;
1293
 
    }
1294
 
 
1295
 
    return typedNode;
1296
 
}
1297
 
 
1298
 
//
1299
 
// This function returns the value of a particular field inside a constant structure from the symbol table. 
1300
 
// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
1301
 
// function and returns the parse-tree with the values of the embedded/nested struct.
1302
 
//
1303
 
TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
1304
 
{
1305
 
    TTypeList* fields = node->getType().getStruct();
1306
 
    TIntermTyped *typedNode;
1307
 
    int instanceSize = 0;
1308
 
    unsigned int index = 0;
1309
 
    TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
1310
 
    TIntermAggregate* aggregateNode = node->getAsAggregate();
1311
 
 
1312
 
    for ( index = 0; index < fields->size(); ++index) {
1313
 
        if ((*fields)[index].type->getFieldName() == identifier) {
1314
 
            break;
1315
 
        } else {
1316
 
            if ((*fields)[index].type->getStruct())
1317
 
                //?? We should actually be calling getStructSize() function and not setStructSize. This problem occurs in case
1318
 
                // of nested/embedded structs.                
1319
 
                instanceSize += (*fields)[index].type->setStructSize((*fields)[index].type->getStruct());
1320
 
            else
1321
 
                instanceSize += (*fields)[index].type->getInstanceSize();
1322
 
        }
1323
 
    }
1324
 
 
1325
 
    if (tempConstantNode) {
1326
 
         constUnion* constArray = tempConstantNode->getUnionArrayPointer();
1327
 
 
1328
 
         typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
1329
 
    } else if (aggregateNode) {
1330
 
        // for a case like constStruct(1,v3).i where structure fields is int i and vec3 v3.
1331
 
 
1332
 
        constUnion* unionArray = new constUnion[aggregateNode->getType().getStructSize()];                        
1333
 
    
1334
 
        bool returnVal = false;
1335
 
        if (aggregateNode->getAsAggregate()->getSequence().size() == 1 && aggregateNode->getAsAggregate()->getSequence()[0]->getAsTyped()->getAsConstantUnion())  {
1336
 
            returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable,  aggregateNode->getType(), true);
1337
 
        }
1338
 
        else {
1339
 
            returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType());
1340
 
        }
1341
 
 
1342
 
        if (!returnVal)
1343
 
            typedNode = intermediate.addConstantUnion(unionArray+instanceSize, aggregateNode->getType(), line);
1344
 
        else
1345
 
            return 0;
1346
 
 
1347
 
    } else {
1348
 
        error(line, "No Aggregate or Constant Union node available", "Internal Error", "");
1349
 
        recover();
1350
 
 
1351
 
        return 0;
1352
 
    }
1353
 
 
1354
 
    return typedNode;
1355
 
}
1356
 
 
1357
 
//
1358
 
// Initialize all supported extensions to disable
1359
 
//
1360
 
void TParseContext::initializeExtensionBehavior()
1361
 
{
1362
 
    //
1363
 
    // example code: extensionBehavior["test"] = EDisable; // where "test" is the name of 
1364
 
    // supported extension
1365
 
    //
1366
 
}
1367
 
 
1368
 
OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
1369
 
 
1370
 
bool InitializeParseContextIndex()
1371
 
{
1372
 
    if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
1373
 
        assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
1374
 
        return false;
1375
 
    }
1376
 
 
1377
 
    //
1378
 
    // Allocate a TLS index.
1379
 
    //
1380
 
    GlobalParseContextIndex = OS_AllocTLSIndex();
1381
 
    
1382
 
    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1383
 
        assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
1384
 
        return false;
1385
 
    }
1386
 
 
1387
 
    return true;
1388
 
}
1389
 
 
1390
 
bool InitializeGlobalParseContext()
1391
 
{
1392
 
    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1393
 
        assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised");
1394
 
        return false;
1395
 
    }
1396
 
 
1397
 
    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
1398
 
    if (lpParseContext != 0) {
1399
 
        assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
1400
 
        return false;
1401
 
    }
1402
 
 
1403
 
    TThreadParseContext *lpThreadData = new TThreadParseContext();
1404
 
    if (lpThreadData == 0) {
1405
 
        assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
1406
 
        return false;
1407
 
    }
1408
 
 
1409
 
    lpThreadData->lpGlobalParseContext = 0;
1410
 
    OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
1411
 
 
1412
 
    return true;
1413
 
}
1414
 
 
1415
 
TParseContextPointer& GetGlobalParseContext()
1416
 
{
1417
 
    //
1418
 
    // Minimal error checking for speed
1419
 
    //
1420
 
 
1421
 
    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
1422
 
 
1423
 
    return lpParseContext->lpGlobalParseContext;
1424
 
}
1425
 
 
1426
 
bool FreeParseContext()
1427
 
{
1428
 
    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1429
 
        assert(0 && "FreeParseContext(): Parse Context index not initalised");
1430
 
        return false;
1431
 
    }
1432
 
 
1433
 
    TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
1434
 
    if (lpParseContext)
1435
 
        delete lpParseContext;
1436
 
 
1437
 
    return true;
1438
 
}
1439
 
 
1440
 
bool FreeParseContextIndex()
1441
 
{
1442
 
    OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
1443
 
 
1444
 
    if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1445
 
        assert(0 && "FreeParseContextIndex(): Parse Context index not initalised");
1446
 
        return false;
1447
 
    }
1448
 
 
1449
 
    GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
1450
 
 
1451
 
    return OS_FreeTLSIndex(tlsiIndex);
1452
 
}