2
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
5
//Redistribution and use in source and binary forms, with or without
6
//modification, are permitted provided that the following conditions
9
// Redistributions of source code must retain the above copyright
10
// notice, this list of conditions and the following disclaimer.
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.
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.
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.
35
#include "ParseHelper.h"
36
#include "Include/InitializeParseContext.h"
37
#include "osinclude.h"
39
///////////////////////////////////////////////////////////////////////
41
// Sub- vector and matrix fields
43
////////////////////////////////////////////////////////////////////////
46
// Look at a '.' field selector string and change it into offsets
49
bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
51
fields.num = (int) compString.size();
53
error(line, "illegal vector field selection", compString.c_str(), "");
63
for (int i = 0; i < fields.num; ++i) {
64
switch (compString[i]) {
66
fields.offsets[i] = 0;
70
fields.offsets[i] = 0;
74
fields.offsets[i] = 0;
78
fields.offsets[i] = 1;
82
fields.offsets[i] = 1;
86
fields.offsets[i] = 1;
90
fields.offsets[i] = 2;
94
fields.offsets[i] = 2;
98
fields.offsets[i] = 2;
103
fields.offsets[i] = 3;
107
fields.offsets[i] = 3;
111
fields.offsets[i] = 3;
115
error(line, "illegal vector field selection", compString.c_str(), "");
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(), "");
127
if (fieldSet[i] != fieldSet[i-1]) {
128
error(line, "illegal - vector component fields not from the same set", compString.c_str(), "");
139
// Look at a '.' field selector string and change it into offsets
142
bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
144
fields.wholeRow = false;
145
fields.wholeCol = false;
149
if (compString.size() != 2) {
150
error(line, "illegal length of matrix field selection", compString.c_str(), "");
154
if (compString[0] == '_') {
155
if (compString[1] < '0' || compString[1] > '3') {
156
error(line, "illegal matrix field selection", compString.c_str(), "");
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(), "");
166
fields.wholeRow = true;
167
fields.row = compString[0] - '0';
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(), "");
174
fields.row = compString[0] - '0';
175
fields.col = compString[1] - '0';
178
if (fields.row >= matSize || fields.col >= matSize) {
179
error(line, "matrix field selection out of range", compString.c_str(), "");
186
///////////////////////////////////////////////////////////////////////
190
////////////////////////////////////////////////////////////////////////
193
// Track whether errors have occurred.
195
void TParseContext::recover()
197
recoveredFromError = true;
201
// Used by flex/bison to output all syntax and parsing errors.
203
void C_DECL TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken,
204
const char *szExtraInfoFormat, ...)
206
char szExtraInfo[400];
209
va_start(marker, szExtraInfoFormat);
211
_vsnprintf(szExtraInfo, sizeof(szExtraInfo), szExtraInfoFormat, marker);
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";
224
// Same error message for all places assignments don't work.
226
void TParseContext::assignError(int line, const char* op, TString left, TString right)
228
error(line, "", op, "cannot convert from '%s' to '%s'",
229
right.c_str(), left.c_str());
233
// Same error message for all places unary operations don't work.
235
void TParseContext::unaryOpError(int line, char* op, TString operand)
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());
243
// Same error message for all binary operations don't work.
245
void TParseContext::binaryOpError(int line, char* op, TString left, TString right)
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());
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.
257
// Returns true if the was an error.
259
bool TParseContext::lValueErrorCheck(int line, char* op, TIntermTyped* node)
261
TIntermSymbol* symNode = node->getAsSymbolNode();
262
TIntermBinary* binaryNode = node->getAsBinaryNode();
267
switch(binaryNode->getOp()) {
269
case EOpIndexIndirect:
270
case EOpIndexDirectStruct:
271
return lValueErrorCheck(line, op, binaryNode->getLeft());
272
case EOpVectorSwizzle:
273
errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
275
int offset[4] = {0,0,0,0};
277
TIntermTyped* rightNode = binaryNode->getRight();
278
TIntermAggregate *aggrNode = rightNode->getAsAggregate();
280
for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
281
p != aggrNode->getSequence().end(); p++) {
282
int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->iConst;
284
if (offset[value] > 1) {
285
error(line, " l-value of swizzle cannot have duplicate components", op, "", "");
296
error(line, " l-value required", op, "", "");
302
const char* symbol = 0;
304
symbol = symNode->getSymbol().c_str();
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;
319
// Type that can't be written to?
321
switch (node->getBasicType()) {
326
case EbtSampler1DShadow:
327
case EbtSampler2DShadow:
328
message = "can't modify a sampler";
331
message = "can't modify void";
338
if (message == 0 && binaryNode == 0 && symNode == 0) {
339
error(line, " l-value required", op, "", "");
346
// Everything else is okay, no error.
352
// If we get here, we have an error and a message.
355
error(line, " l-value required", op, "\"%s\" (%s)", symbol, message);
357
error(line, " l-value required", op, "(%s)", message);
363
// Both test, and if necessary spit out an error, to see if the node is really
366
// Returns true if the was an error.
368
bool TParseContext::constErrorCheck(TIntermTyped* node)
370
if (node->getQualifier() == EvqConst)
373
error(node->getLine(), "constant expression required", "", "");
379
// Both test, and if necessary spit out an error, to see if the node is really
382
// Returns true if the was an error.
384
bool TParseContext::integerErrorCheck(TIntermTyped* node, char* token)
386
if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
389
error(node->getLine(), "integer expression required", token, "");
395
// Both test, and if necessary spit out an error, to see if we are currently
398
// Returns true if the was an error.
400
bool TParseContext::globalErrorCheck(int line, bool global, char* token)
405
error(line, "only allowed at global scope", token, "");
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.
415
// Returns true if there was an error.
417
bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
419
if (symbolTable.atBuiltInLevel() ||
420
identifier.substr(0, 3) != TString("gl_"))
423
error(line, "reserved built-in name", "gl_", "");
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
433
// Returns true if there was an error in construction.
435
bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
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;
455
error(line, "expected constructor", "Internal Error", "");
459
bool constructingMatrix = false;
461
case EOpConstructMat2:
462
case EOpConstructMat3:
463
case EOpConstructMat4:
464
constructingMatrix = true;
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.
477
bool constType = true;
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;
487
if (op != EOpConstructStruct && size >= type->getInstanceSize())
489
if (function[i].type->getQualifier() != EvqConst)
494
type->changeQualifier(EvqConst);
496
if (matrixInMatrix) {
497
error(line, "constructing matrix from matrix", "constructor", "(reserved)");
502
error(line, "too many arguments", "constructor", "");
506
if (size != 1 && size < type->getInstanceSize() || (size < 1) && op == EOpConstructStruct) {
507
error(line, "not enough data provided for construction", "constructor", "");
511
TIntermTyped* typed = node->getAsTyped();
513
error(line, "constructor argument does not have a type", "constructor", "");
516
if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
517
error(line, "cannot convert a sampler", "constructor", "");
520
if (typed->getBasicType() == EbtVoid) {
521
error(line, "cannot convert a void", "constructor", "");
528
// This function checks to see if a void variable has been declared and raise an error message for such a case
530
// returns true in case of an error
532
bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
534
if (pubType.type == EbtVoid) {
535
error(line, "illegal use of type 'void'", identifier.c_str(), "");
542
// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
544
// returns true in case of an error
546
bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
548
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
549
error(line, "boolean expression expected", "", "");
556
// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
558
// returns true in case of an error
560
bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
562
if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
563
error(line, "boolean expression expected", "", "");
570
bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
572
if (pType.type == EbtStruct) {
573
if (containsSampler(*pType.userDef)) {
574
error(line, reason, TType::getBasicString(pType.type), "(structure contains a sampler)");
580
} else if (IsSampler(pType.type)) {
581
error(line, reason, TType::getBasicString(pType.type), "");
589
bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
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), "");
598
if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
604
bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
606
if ((qualifier == EvqOut || qualifier == EvqInOut) &&
607
type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
608
error(line, "samplers cannot be output parameters", type.getBasicString(), "");
615
bool TParseContext::containsSampler(TType& type)
617
if (IsSampler(type.getBasicType()))
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))
631
bool TParseContext::insertBuiltInArrayAtGlobalLevel()
633
TString *name = NewPoolTString("gl_TexCoord");
634
TSymbol* symbol = symbolTable.find(*name);
636
error(0, "INTERNAL ERROR finding symbol", name->c_str(), "");
639
TVariable* variable = static_cast<TVariable*>(symbol);
641
TVariable* newVariable = new TVariable(name, variable->getType());
643
if (! symbolTable.insert(*newVariable)) {
645
error(0, "INTERNAL ERROR inserting new symbol", name->c_str(), "");
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.
656
// size == 0 means no specified size.
658
// Returns true if there was an error.
660
bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TIntermTyped* size)
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.
668
// Can the type be an array?
670
if (type.array || type.qualifier == EvqAttribute || type.qualifier == EvqConst) {
671
error(line, "cannot declare arrays of this type", TType(type).getCompleteString().c_str(), "");
677
// size will be 0 if there is no size declared, otherwise it contains the size
680
TIntermConstantUnion* constant = 0;
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(), "");
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))
696
TVariable* variable = new TVariable(&identifier, TType(type));
699
variable->getType().setArraySize(constant->getUnionArrayPointer()->iConst);
701
if (! symbolTable.insert(*variable)) {
703
error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
707
if (! symbol->isVariable()) {
708
error(line, "variable expected", identifier.c_str(), "");
712
TVariable* variable = static_cast<TVariable*>(symbol);
713
if (! variable->getType().isArray()) {
714
error(line, "redeclaring non-array as array", identifier.c_str(), "");
717
if (variable->getType().getArraySize() > 0) {
718
error(line, "redeclaration of array with size", identifier.c_str(), "");
722
if (variable->getType() != TType(type)) {
723
error(line, "redeclaration of array with a different type", identifier.c_str(), "");
727
TType* t = variable->getArrayInformationType();
729
if (t->getMaxArraySize() > constant->getUnionArrayPointer()->iConst) {
730
error(line, "higher index value already used for the array", identifier.c_str(), "");
733
t->setArraySize(constant->getUnionArrayPointer()->iConst);
734
t = t->getArrayInformationType();
738
variable->getType().setArraySize(constant->getUnionArrayPointer()->iConst);
741
if (voidErrorCheck(line, identifier, type))
747
bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
749
bool builtIn = false;
750
TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
752
error(line, " undeclared identifier", node->getSymbol().c_str(), "");
755
TVariable* variable = static_cast<TVariable*>(symbol);
757
type->setArrayInformationType(variable->getArrayInformationType());
758
variable->updateArrayInformationType(type);
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.
766
variable->getType().setMaxArraySize(size);
767
type->setMaxArraySize(size);
770
while(tt->getArrayInformationType() != 0) {
771
tt = tt->getArrayInformationType();
772
tt->setMaxArraySize(size);
779
// Do semantic checking for a variable declaration that has no initializer,
780
// and update the symbol table.
782
// Returns true if there was an error.
784
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
786
if (reservedErrorCheck(line, identifier))
790
// Make the qualifier make sense, error is issued in a little bit.
792
bool constError = false;
793
if (type.qualifier == EvqConst) {
794
type.qualifier = EvqTemporary;
798
TVariable* variable = new TVariable(&identifier, TType(type));
800
if (! symbolTable.insert(*variable)) {
801
error(line, "redefinition", variable->getName().c_str(), "");
806
error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
810
if (voidErrorCheck(line, identifier, type))
816
bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
818
if (qualifier != EvqConst && qualifier != EvqTemporary) {
819
error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), "");
822
if (qualifier == EvqConst && paramQualifier != EvqIn) {
823
error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
827
if (qualifier == EvqConst)
828
type->changeQualifier(EvqConstReadOnly);
830
type->changeQualifier(paramQualifier);
835
/////////////////////////////////////////////////////////////////////////////////
839
/////////////////////////////////////////////////////////////////////////////////
842
// Look up a function name in the symbol table, and make sure it is a function.
844
// Return the function symbol if found, otherwise 0.
846
const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
848
const TSymbol* symbol = symbolTable.find(call->getMangledName(), builtIn);
851
error(line, "no matching overloaded function found", call->getName().c_str(), "");
855
if (! symbol->isFunction()) {
856
error(line, "function name expected", call->getName().c_str(), "");
860
const TFunction* function = static_cast<const TFunction*>(symbol);
865
// Initializers show up in several places in the grammar. Have one set of
866
// code to handle them here.
868
bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
869
TIntermTyped* initializer, TIntermNode*& intermNode)
871
if (reservedErrorCheck(line, identifier))
874
if (voidErrorCheck(line, identifier, pType))
878
// add variable to symbol table
880
TVariable* variable = new TVariable(&identifier, TType(pType));
881
if (! symbolTable.insert(*variable)) {
882
error(line, "redefinition", variable->getName().c_str(), "");
884
// don't delete variable, it's used by error recovery, and the pool
885
// pop will take care of the memory
889
// identifier must be of type constant, a global, or a temporary
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(), "");
897
// test for and propagate constant
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);
906
if (TType(pType) != initializer->getType()) {
907
error(line, " non-matching types for const initializer ",
908
variable->getType().getQualifierString(), "");
909
variable->getType().changeQualifier(EvqTemporary);
912
if (initializer->getAsConstantUnion()) {
913
constUnion* unionArray = variable->getConstPointer();
915
if (pType.size == 1 && TType(pType).getBasicType() != EbtStruct) {
916
switch (pType.type ) {
918
unionArray->iConst = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0].iConst;
921
unionArray->fConst = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0].fConst;
924
unionArray->bConst = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0].bConst;
927
error(line, " cannot initialize constant of this type", "", "");
931
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
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);
940
returnVal = intermediate.parseConstTree(line, initializer, unionArray, initializer->getAsAggregate()->getOp(), symbolTable, variable->getType());
943
constUnion *arrayUnion = unionArray;
946
variable->getType().changeQualifier(EvqTemporary);
949
} else if (initializer->getAsSymbolNode()) {
950
const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
951
const TVariable* tVar = static_cast<const TVariable*>(symbol);
953
constUnion* constArray = tVar->getConstPointer();
954
variable->shareConstPointer(constArray);
956
error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
957
variable->getType().changeQualifier(EvqTemporary);
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());
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
979
bool TParseContext::canNodeBeRemoved(TIntermNode* childNode)
981
TIntermAggregate *aggrNode = childNode->getAsAggregate();
985
if (!aggrNode->isConstructor() || aggrNode->getOp() == EOpConstructStruct)
988
bool allConstant = true;
990
// check if all the child nodes are constants so that they can be inserted into
993
TIntermSequence &childSequenceVector = aggrNode->getSequence() ;
994
for (TIntermSequence::iterator p = childSequenceVector.begin();
995
p != childSequenceVector.end(); p++) {
996
if (!(*p)->getAsTyped()->getAsConstantUnion())
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.
1007
// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
1009
TIntermTyped* TParseContext::addConstructor(TIntermNode* node, TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
1014
TIntermAggregate* aggrNode = node->getAsAggregate();
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();
1026
if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
1033
TIntermTyped *newNode;
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", "");
1043
return constructStruct(node, (*list).type, 1, node->getLine(), false);
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);
1057
// Handle list of arguments.
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
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", "");
1070
int paramCount = 0; // keeps a track of the constructor parameter number being checked
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.
1076
for (TIntermSequence::iterator p = sequenceVector.begin();
1077
p != sequenceVector.end(); p++, paramCount++) {
1079
if (op == EOpConstructStruct) {
1080
newNode = constructStruct(*p, (list[paramCount]).type, paramCount+1, node->getLine(), true);
1084
newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
1087
if (canNodeBeRemoved(newNode))
1088
intermediate.removeChildNode(sequenceVector, *type, paramCount, p, newNode->getAsAggregate());
1094
sequenceVector.erase(p);
1095
sequenceVector.insert(p, newNode);
1099
return intermediate.setAggregateOperator(aggrNode, op, line);
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.
1107
// Returns 0 for an error or the constructed node.
1109
TIntermTyped* TParseContext::constructBuiltIn(TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
1111
TIntermTyped* newNode;
1115
// First, convert types as needed.
1118
case EOpConstructVec2:
1119
case EOpConstructVec3:
1120
case EOpConstructVec4:
1121
case EOpConstructMat2:
1122
case EOpConstructMat3:
1123
case EOpConstructMat4:
1124
case EOpConstructFloat:
1125
basicOp = EOpConstructFloat;
1128
case EOpConstructIVec2:
1129
case EOpConstructIVec3:
1130
case EOpConstructIVec4:
1131
case EOpConstructInt:
1132
basicOp = EOpConstructInt;
1135
case EOpConstructBVec2:
1136
case EOpConstructBVec3:
1137
case EOpConstructBVec4:
1138
case EOpConstructBool:
1139
basicOp = EOpConstructBool;
1143
error(line, "unsupported construction", "", "");
1148
newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
1150
error(line, "can't convert", "constructor", "");
1155
// Now, if there still isn't an operation to do the construction, and we need one, add one.
1158
// Otherwise, skip out early.
1159
if (subset || newNode != node && newNode->getType() == *type)
1162
// setAggregateOperator will insert a new node for the constructor, as needed.
1163
return intermediate.setAggregateOperator(newNode, op, line);
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.
1169
// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
1171
TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
1173
if (*type == node->getAsTyped()->getType()) {
1175
return node->getAsTyped();
1177
return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
1179
error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
1180
node->getAsTyped()->getType().getBasicString(), type->getBasicString());
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.
1194
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
1196
TIntermTyped* typedNode;
1197
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1198
TIntermAggregate* aggregateNode = node->getAsAggregate();
1200
constUnion *unionArray;
1201
if (tempConstantNode) {
1202
unionArray = tempConstantNode->getUnionArrayPointer();
1204
if (!unionArray) { // this error message should never be raised
1205
infoSink.info.message(EPrefixInternalError, "constUnion not initialized in addConstVectorNode function", line);
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()];
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);
1219
returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType());
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", "");
1232
constUnion* constArray = new constUnion[fields.num];
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]);
1238
fields.offsets[i] = 0;
1241
constArray[i] = unionArray[fields.offsets[i]];
1244
typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
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)
1254
TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
1256
TIntermTyped* typedNode;
1257
TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1258
TIntermAggregate* aggregateNode = node->getAsAggregate();
1260
if (index >= node->getType().getNominalSize()) {
1261
error(line, "", "[", "matrix field selection out of range '%d'", index);
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();
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);
1280
returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType());
1284
typedNode = intermediate.addConstantUnion(&unionArray[size*index], aggregateNode->getType(), line);
1289
error(line, "No Aggregate or Constant Union node available", "Internal Error", "");
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.
1303
TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
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();
1312
for ( index = 0; index < fields->size(); ++index) {
1313
if ((*fields)[index].type->getFieldName() == identifier) {
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());
1321
instanceSize += (*fields)[index].type->getInstanceSize();
1325
if (tempConstantNode) {
1326
constUnion* constArray = tempConstantNode->getUnionArrayPointer();
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.
1332
constUnion* unionArray = new constUnion[aggregateNode->getType().getStructSize()];
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);
1339
returnVal = intermediate.parseConstTree(line, aggregateNode, unionArray, aggregateNode->getOp(), symbolTable, aggregateNode->getType());
1343
typedNode = intermediate.addConstantUnion(unionArray+instanceSize, aggregateNode->getType(), line);
1348
error(line, "No Aggregate or Constant Union node available", "Internal Error", "");
1358
// Initialize all supported extensions to disable
1360
void TParseContext::initializeExtensionBehavior()
1363
// example code: extensionBehavior["test"] = EDisable; // where "test" is the name of
1364
// supported extension
1368
OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
1370
bool InitializeParseContextIndex()
1372
if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
1373
assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
1378
// Allocate a TLS index.
1380
GlobalParseContextIndex = OS_AllocTLSIndex();
1382
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1383
assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
1390
bool InitializeGlobalParseContext()
1392
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1393
assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised");
1397
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
1398
if (lpParseContext != 0) {
1399
assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
1403
TThreadParseContext *lpThreadData = new TThreadParseContext();
1404
if (lpThreadData == 0) {
1405
assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
1409
lpThreadData->lpGlobalParseContext = 0;
1410
OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
1415
TParseContextPointer& GetGlobalParseContext()
1418
// Minimal error checking for speed
1421
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
1423
return lpParseContext->lpGlobalParseContext;
1426
bool FreeParseContext()
1428
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1429
assert(0 && "FreeParseContext(): Parse Context index not initalised");
1433
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
1435
delete lpParseContext;
1440
bool FreeParseContextIndex()
1442
OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
1444
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1445
assert(0 && "FreeParseContextIndex(): Parse Context index not initalised");
1449
GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
1451
return OS_FreeTLSIndex(tlsiIndex);