summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/ParseHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/ParseHelper.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/ParseHelper.cpp355
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.