diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/ParseHelper.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/ParseHelper.cpp | 355 |
1 files changed, 215 insertions, 140 deletions
diff --git a/src/3rdparty/angle/src/compiler/ParseHelper.cpp b/src/3rdparty/angle/src/compiler/ParseHelper.cpp index 441ff35e00..1f8538e6a4 100644 --- a/src/3rdparty/angle/src/compiler/ParseHelper.cpp +++ b/src/3rdparty/angle/src/compiler/ParseHelper.cpp @@ -22,7 +22,7 @@ // Look at a '.' field selector string and change it into offsets // for a vector. // -bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line) +bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line) { fields.num = (int) compString.size(); if (fields.num > 4) { @@ -115,7 +115,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV // Look at a '.' field selector string and change it into offsets // for a matrix. // -bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line) +bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line) { fields.wholeRow = false; fields.wholeCol = false; @@ -175,22 +175,24 @@ void TParseContext::recover() // // Used by flex/bison to output all syntax and parsing errors. // -void TParseContext::error(TSourceLoc loc, +void TParseContext::error(const TSourceLoc& loc, const char* reason, const char* token, const char* extraInfo) { pp::SourceLocation srcLoc; - DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line); + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; diagnostics.writeInfo(pp::Diagnostics::ERROR, srcLoc, reason, token, extraInfo); } -void TParseContext::warning(TSourceLoc loc, +void TParseContext::warning(const TSourceLoc& loc, const char* reason, const char* token, const char* extraInfo) { pp::SourceLocation srcLoc; - DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line); + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; diagnostics.writeInfo(pp::Diagnostics::WARNING, srcLoc, reason, token, extraInfo); } @@ -203,7 +205,7 @@ void TParseContext::trace(const char* str) // // Same error message for all places assignments don't work. // -void TParseContext::assignError(int line, const char* op, TString left, TString right) +void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right) { std::stringstream extraInfoStream; extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'"; @@ -214,7 +216,7 @@ void TParseContext::assignError(int line, const char* op, TString left, TString // // Same error message for all places unary operations don't work. // -void TParseContext::unaryOpError(int line, const char* op, TString operand) +void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand) { std::stringstream extraInfoStream; extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand @@ -226,7 +228,7 @@ void TParseContext::unaryOpError(int line, const char* op, TString operand) // // Same error message for all binary operations don't work. // -void TParseContext::binaryOpError(int line, const char* op, TString left, TString right) +void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right) { std::stringstream extraInfoStream; extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left @@ -235,7 +237,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin error(line, " wrong operand types ", op, extraInfo.c_str()); } -bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){ +bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){ if (!checksPrecisionErrors) return false; switch( type ){ @@ -263,7 +265,7 @@ bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicTy // // Returns true if the was an error. // -bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node) +bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node) { TIntermSymbol* symNode = node->getAsSymbolNode(); TIntermBinary* binaryNode = node->getAsBinaryNode(); @@ -317,7 +319,6 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod case EvqAttribute: message = "can't modify an attribute"; break; case EvqUniform: message = "can't modify a uniform"; break; case EvqVaryingIn: message = "can't modify a varying"; break; - case EvqInput: message = "can't modify an input"; break; case EvqFragCoord: message = "can't modify gl_FragCoord"; break; case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break; case EvqPointCoord: message = "can't modify gl_PointCoord"; break; @@ -409,7 +410,7 @@ bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) // // Returns true if the was an error. // -bool TParseContext::globalErrorCheck(int line, bool global, const char* token) +bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token) { if (global) return false; @@ -428,7 +429,7 @@ bool TParseContext::globalErrorCheck(int line, bool global, const char* token) // // Returns true if there was an error. // -bool TParseContext::reservedErrorCheck(int line, const TString& identifier) +bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier) { static const char* reservedErrMsg = "reserved built-in name"; if (!symbolTable.atBuiltInLevel()) { @@ -466,7 +467,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier) // // Returns true if there was an error in construction. // -bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type) +bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type) { *type = function.getReturnType(); @@ -487,7 +488,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction // again, there is an extra argument, so 'overfull' will become true. // - int size = 0; + size_t size = 0; bool constType = true; bool full = false; bool overFull = false; @@ -534,7 +535,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction return true; } - if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) { + if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) { error(line, "Number of constructor parameters does not match the number of structure fields", "constructor"); return true; } @@ -568,7 +569,7 @@ bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction // // returns true in case of an error // -bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType) +bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType) { if (pubType.type == EbtVoid) { error(line, "illegal use of type 'void'", identifier.c_str()); @@ -582,7 +583,7 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP // // returns true in case of an error // -bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type) +bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type) { if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) { error(line, "boolean expression expected", ""); @@ -596,7 +597,7 @@ bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type) // // returns true in case of an error // -bool TParseContext::boolErrorCheck(int line, const TPublicType& pType) +bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType) { if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { error(line, "boolean expression expected", ""); @@ -606,7 +607,7 @@ bool TParseContext::boolErrorCheck(int line, const TPublicType& pType) return false; } -bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason) +bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason) { if (pType.type == EbtStruct) { if (containsSampler(*pType.userDef)) { @@ -625,7 +626,7 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const return false; } -bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType) +bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType) { if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && pType.type == EbtStruct) { @@ -640,7 +641,7 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType return false; } -bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type) +bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type) { if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) { @@ -657,9 +658,9 @@ bool TParseContext::containsSampler(TType& type) return true; if (type.getBasicType() == EbtStruct) { - TTypeList& structure = *type.getStruct(); - for (unsigned int i = 0; i < structure.size(); ++i) { - if (containsSampler(*structure[i].type)) + const TFieldList& fields = type.getStruct()->fields(); + for (unsigned int i = 0; i < fields.size(); ++i) { + if (containsSampler(*fields[i]->type())) return true; } } @@ -672,7 +673,7 @@ bool TParseContext::containsSampler(TType& type) // // Returns true if there was an error. // -bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) +bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size) { TIntermConstantUnion* constant = expr->getAsConstantUnion(); if (constant == 0 || constant->getBasicType() != EbtInt) { @@ -696,7 +697,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) // // Returns true if there is an error. // -bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) +bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type) { if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) { error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); @@ -711,7 +712,7 @@ bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) // // Returns true if there is an error. // -bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) +bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type) { // // Can the type be an array? @@ -732,7 +733,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) // // Returns true if there was an error. // -bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable) +bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable) { // // Don't check for reserved word use until after we know it's not in the symbol table, @@ -777,16 +778,6 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t return true; } - TType* t = variable->getArrayInformationType(); - while (t != 0) { - if (t->getMaxArraySize() > type.arraySize) { - error(line, "higher index value already used for the array", identifier.c_str()); - return true; - } - t->setArraySize(type.arraySize); - t = t->getArrayInformationType(); - } - if (type.arraySize) variable->getType().setArraySize(type.arraySize); } @@ -797,56 +788,12 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType t return false; } -bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line) -{ - bool builtIn = false; - TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn); - if (symbol == 0) { - error(line, " undeclared identifier", node->getSymbol().c_str()); - return true; - } - TVariable* variable = static_cast<TVariable*>(symbol); - - type->setArrayInformationType(variable->getArrayInformationType()); - variable->updateArrayInformationType(type); - - // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers - // its an error - if (node->getSymbol() == "gl_FragData") { - TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn); - ASSERT(fragData); - - int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst(); - if (fragDataValue <= size) { - error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers"); - return true; - } - } - - // we dont want to update the maxArraySize when this flag is not set, we just want to include this - // node type in the chain of node types so that its updated when a higher maxArraySize comes in. - if (!updateFlag) - return false; - - size++; - variable->getType().setMaxArraySize(size); - type->setMaxArraySize(size); - TType* tt = type; - - while(tt->getArrayInformationType() != 0) { - tt = tt->getArrayInformationType(); - tt->setMaxArraySize(size); - } - - return false; -} - // // Enforce non-initializer type/qualifier rules. // // Returns true if there was an error. // -bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array) +bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array) { if (type.qualifier == EvqConst) { @@ -878,7 +825,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli // // Returns true if there was an error. // -bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable) +bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable) { if (reservedErrorCheck(line, identifier)) recover(); @@ -898,7 +845,7 @@ bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType return false; } -bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type) +bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type) { if (qualifier != EvqConst && qualifier != EvqTemporary) { error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier)); @@ -917,7 +864,7 @@ bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier p return false; } -bool TParseContext::extensionErrorCheck(int line, const TString& extension) +bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension) { const TExtensionBehavior& extBehavior = extensionBehavior(); TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); @@ -945,18 +892,17 @@ bool TParseContext::supportsExtension(const char* extension) return (iter != extbehavior.end()); } -void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior) +bool TParseContext::isExtensionEnabled(const char* extension) const { - pp::SourceLocation loc; - DecodeSourceLoc(line, &loc.file, &loc.line); - directiveHandler.handleExtension(loc, extName, behavior); -} + const TExtensionBehavior& extbehavior = extensionBehavior(); + TExtensionBehavior::const_iterator iter = extbehavior.find(extension); -void TParseContext::handlePragmaDirective(int line, const char* name, const char* value) -{ - pp::SourceLocation loc; - DecodeSourceLoc(line, &loc.file, &loc.line); - directiveHandler.handlePragma(loc, name, value); + if (iter == extbehavior.end()) + { + return false; + } + + return (iter->second == EBhEnable || iter->second == EBhRequire); } ///////////////////////////////////////////////////////////////////////////////// @@ -970,12 +916,13 @@ void TParseContext::handlePragmaDirective(int line, const char* name, const char // // Return the function symbol if found, otherwise 0. // -const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn) +const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn) { // First find by unmangled name to check whether the function name has been // hidden by a variable name or struct typename. + // If a function is found, check for one with a matching argument list. const TSymbol* symbol = symbolTable.find(call->getName(), builtIn); - if (symbol == 0) { + if (symbol == 0 || symbol->isFunction()) { symbol = symbolTable.find(call->getMangledName(), builtIn); } @@ -996,7 +943,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu // Initializers show up in several places in the grammar. Have one set of // code to handle them here. // -bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, +bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { TType type = TType(pType); @@ -1048,13 +995,7 @@ bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPu return true; } if (initializer->getAsConstantUnion()) { - ConstantUnion* unionArray = variable->getConstPointer(); - - if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) { - *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0]; - } else { - variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); - } + variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); } else if (initializer->getAsSymbolNode()) { const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); const TVariable* tVar = static_cast<const TVariable*>(symbol); @@ -1108,16 +1049,16 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) // // Returns 0 for an error or the constructed node (aggregate or typed) for no error. // -TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line) +TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line) { if (node == 0) return 0; TIntermAggregate* aggrNode = node->getAsAggregate(); - TTypeList::const_iterator memberTypes; + TFieldList::const_iterator memberFields; if (op == EOpConstructStruct) - memberTypes = type->getStruct()->begin(); + memberFields = type->getStruct()->fields().begin(); TType elementType = *type; if (type->isArray()) @@ -1139,7 +1080,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type if (type->isArray()) newNode = constructStruct(node, &elementType, 1, node->getLine(), false); else if (op == EOpConstructStruct) - newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false); + newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false); else newNode = constructBuiltIn(type, op, node, node->getLine(), false); @@ -1170,7 +1111,7 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type if (type->isArray()) newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); else if (op == EOpConstructStruct) - newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true); + newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true); else newNode = constructBuiltIn(type, op, *p, node->getLine(), true); @@ -1216,7 +1157,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co // // Returns 0 for an error or the constructed node. // -TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset) +TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) { TIntermTyped* newNode; TOperator basicOp; @@ -1278,7 +1219,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, T // // Returns 0 for an error or the input node itself if the expected and the given parameter types match. // -TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset) +TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset) { if (*type == node->getAsTyped()->getType()) { if (subset) @@ -1305,7 +1246,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of // a constant matrix. // -TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1327,7 +1268,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy ConstantUnion* constArray = new ConstantUnion[fields.num]; for (int i = 0; i < fields.num; i++) { - if (fields.offsets[i] >= node->getType().getObjectSize()) { + if (fields.offsets[i] >= node->getType().getNominalSize()) { std::stringstream extraInfoStream; extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; std::string extraInfo = extraInfoStream.str(); @@ -1349,7 +1290,7 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) // -TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1384,7 +1325,7 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T // to the function could either be a symbol node (a[0] where a is a constant array)that represents a // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure) // -TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line) { TIntermTyped* typedNode; TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); @@ -1400,9 +1341,8 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS index = 0; } - int arrayElementSize = arrayElementType.getObjectSize(); - if (tempConstantNode) { + size_t arrayElementSize = arrayElementType.getObjectSize(); ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); } else { @@ -1421,22 +1361,21 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr // function and returns the parse-tree with the values of the embedded/nested struct. // -TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line) +TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line) { - const TTypeList* fields = node->getType().getStruct(); - TIntermTyped *typedNode; - int instanceSize = 0; - unsigned int index = 0; - TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); - - for ( index = 0; index < fields->size(); ++index) { - if ((*fields)[index].type->getFieldName() == identifier) { + const TFieldList& fields = node->getType().getStruct()->fields(); + + size_t instanceSize = 0; + for (size_t index = 0; index < fields.size(); ++index) { + if (fields[index]->name() == identifier) { break; } else { - instanceSize += (*fields)[index].type->getObjectSize(); + instanceSize += fields[index]->type()->getObjectSize(); } } + TIntermTyped* typedNode = 0; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); if (tempConstantNode) { ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); @@ -1451,7 +1390,7 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n return typedNode; } -bool TParseContext::enterStructDeclaration(int line, const TString& identifier) +bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier) { ++structNestingLevel; @@ -1477,24 +1416,26 @@ const int kWebGLMaxStructNesting = 4; } // namespace -bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType) +bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field) { if (!isWebGLBasedSpec(shaderSpec)) { return false; } - if (fieldType.getBasicType() != EbtStruct) { + if (field.type()->getBasicType() != EbtStruct) { return false; } // We're already inside a structure definition at this point, so add // one to the field's struct nesting. - if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) { - std::stringstream extraInfoStream; - extraInfoStream << "Reference of struct type " << fieldType.getTypeName() - << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "", extraInfo.c_str()); + if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) { + std::stringstream reasonStream; + reasonStream << "Reference of struct type " + << field.type()->getStruct()->name().c_str() + << " exceeds maximum allowed nesting level of " + << kWebGLMaxStructNesting; + std::string reason = reasonStream.str(); + error(line, reason.c_str(), field.name().c_str(), ""); return true; } @@ -1502,6 +1443,140 @@ bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldT } // +// Parse an array index expression +// +TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression) +{ + TIntermTyped *indexedExpression = NULL; + + if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector()) + { + if (baseExpression->getAsSymbolNode()) + { + error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str()); + } + else + { + error(location, " left of '[' is not of type array, matrix, or vector ", "expression"); + } + recover(); + } + + if (indexExpression->getQualifier() == EvqConst) + { + int index = indexExpression->getAsConstantUnion()->getIConst(0); + if (index < 0) + { + std::stringstream infoStream; + infoStream << index; + std::string info = infoStream.str(); + error(location, "negative index", info.c_str()); + recover(); + index = 0; + } + if (baseExpression->getType().getQualifier() == EvqConst) + { + if (baseExpression->isArray()) + { + // constant folding for arrays + indexedExpression = addConstArrayNode(index, baseExpression, location); + } + else if (baseExpression->isVector()) + { + // constant folding for vectors + TVectorFields fields; + fields.num = 1; + fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array + indexedExpression = addConstVectorNode(fields, baseExpression, location); + } + else if (baseExpression->isMatrix()) + { + // constant folding for matrices + indexedExpression = addConstMatrixNode(index, baseExpression, location); + } + } + else + { + if (baseExpression->isArray()) + { + if (index >= baseExpression->getType().getArraySize()) + { + std::stringstream extraInfoStream; + extraInfoStream << "array index out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(location, "", "[", extraInfo.c_str()); + recover(); + index = baseExpression->getType().getArraySize() - 1; + } + else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers")) + { + error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled"); + recover(); + index = 0; + } + } + else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index) + { + std::stringstream extraInfoStream; + extraInfoStream << "field selection out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(location, "", "[", extraInfo.c_str()); + recover(); + index = baseExpression->getType().getNominalSize() - 1; + } + + indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index); + indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location); + } + } + else + { + indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); + } + + if (indexedExpression == 0) + { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setFConst(0.0f); + indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location); + } + else if (baseExpression->isArray()) + { + const TType &baseType = baseExpression->getType(); + if (baseType.getStruct()) + { + TType copyOfType(baseType.getStruct()); + indexedExpression->setType(copyOfType); + } + else + { + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix())); + } + + if (baseExpression->getType().getQualifier() == EvqConst) + { + indexedExpression->getTypePointer()->setQualifier(EvqConst); + } + } + else if (baseExpression->isMatrix()) + { + TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize())); + } + else if (baseExpression->isVector()) + { + TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier)); + } + else + { + indexedExpression->setType(baseExpression->getType()); + } + + return indexedExpression; +} + +// // Parse an array of strings using yyparse. // // Returns 0 for success. |