diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 06e93cf0..7ee79554 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -697,10 +697,11 @@ public: virtual int getMatrixCols() const { return matrixCols; } virtual int getMatrixRows() const { return matrixRows; } - virtual bool isScalar() const { return vectorSize == 1 && ! getStruct() && ! isArray(); } + virtual bool isScalar() const { return vectorSize == 1 && ! isStruct() && ! isArray(); } virtual bool isVector() const { return vectorSize > 1; } virtual bool isMatrix() const { return matrixCols ? true : false; } virtual bool isArray() const { return arraySizes != 0; } + virtual bool isStruct() const { return structure != 0; } // Recursively check the structure for any arrays, needed for some error checks virtual bool containsArray() const diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index 135ca9f6..6b8a7cda 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -391,6 +391,7 @@ public: virtual bool isArray() const { return type.isArray(); } virtual bool isVector() const { return type.isVector(); } virtual bool isScalar() const { return type.isScalar(); } + virtual bool isStruct() const { return type.isStruct(); } TString getCompleteString() const { return type.getCompleteString(); } protected: diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp index 8662d32e..9837761a 100644 --- a/glslang/MachineIndependent/Constant.cpp +++ b/glslang/MachineIndependent/Constant.cpp @@ -753,4 +753,56 @@ TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode) return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc()); } +// +// Constant folding of a bracket (array-style) dereference or struct-like dot +// dereference. Can handle any thing except a multi-character swizzle, though +// all swizzles may go to foldSwizzle(). +// +TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, TSourceLoc loc) +{ + TType dereferencedType(node->getType(), index); + dereferencedType.getQualifier().storage = EvqConst; + TIntermTyped* result = 0; + int size = dereferencedType.getObjectSize(); + + int start; + if (node->isStruct()) { + start = 0; + for (int i = 0; i < index; ++i) + start += (*node->getType().getStruct())[i].type->getObjectSize(); + } else + start = size * index; + + result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc); + + if (result == 0) + result = node; + else + result->setType(dereferencedType); + + return result; +} + +// +// Make a constant vector node or constant scalar node, representing a given +// constant vector and constant swizzle into it. +// +TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TVectorFields& fields, TSourceLoc loc) +{ + const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray(); + TConstUnionArray constArray(fields.num); + + for (int i = 0; i < fields.num; i++) + constArray[i] = unionArray[fields.offsets[i]]; + + TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc); + + if (result == 0) + result = node; + else + result->setType(TType(node->getBasicType(), EvqConst, fields.num)); + + return result; +} + } // end namespace glslang diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index e8870311..41f5ea58 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -388,7 +388,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt // // If one's a structure, then no conversions. // - if (type.getStruct() || node->getType().getStruct()) + if (type.isStruct() || node->isStruct()) return 0; // diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index cacaedb7..842d429e 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -459,21 +459,9 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), ""); else error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); - } else if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) { - if (base->isArray()) { - // constant folding for arrays - result = addConstArrayNode(loc, indexValue, base); - } else if (base->isVector()) { - // constant folding for vectors - TVectorFields fields; // need to do it this way because v.xy sends fields integer array - fields.num = 1; - fields.offsets[0] = indexValue; - result = addConstVectorNode(loc, fields, base); - } else if (base->isMatrix()) { - // constant folding for matrices - result = addConstMatrixNode(loc, indexValue, base); - } - } else { + } else if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) + return intermediate.foldDereference(base, indexValue, loc); + else { // at least one of base and index is variable... if (index->getQualifier().storage == EvqConst) { if (base->isArray() && base->getType().getArraySize() == 0) @@ -661,13 +649,9 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped* } } - if (base->getType().getQualifier().storage == EvqConst) { // constant folding for vector fields - result = addConstVectorNode(loc, fields, base); - if (result == 0) - result = base; - else - result->setType(TType(base->getBasicType(), EvqConst, (int) (field).size())); - } else { + if (base->getType().getQualifier().storage == EvqConst) + result = intermediate.foldSwizzle(base, fields, loc); + else { if (fields.num == 1) { TConstUnionArray unionArray(1); unionArray[0].setIConst(fields.offsets[0]); @@ -684,39 +668,27 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped* } else if (base->isMatrix()) error(loc, "field selection not allowed on matrix", ".", ""); else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) { - bool fieldFound = false; TTypeList* fields = base->getType().getStruct(); - if (fields == 0) - error(loc, "structure has no fields", "Internal Error", ""); - else { - unsigned int i; - for (i = 0; i < fields->size(); ++i) { - if ((*fields)[i].type->getFieldName() == field) { - fieldFound = true; - break; - } + bool fieldFound = false; + unsigned int member; + for (member = 0; member < fields->size(); ++member) { + if ((*fields)[member].type->getFieldName() == field) { + fieldFound = true; + break; } - if (fieldFound) { - if (base->getType().getQualifier().storage == EvqConst) { - result = addConstStruct(loc, field, base); - if (result == 0) - result = base; - else { - result->setType(*(*fields)[i].type); - // change the qualifier of the return type, not of the structure field - // as the structure definition is shared between various structures. - result->getWritableType().getQualifier().storage = EvqConst; - } - } else { - TConstUnionArray unionArray(1); - unionArray[0].setIConst(i); - TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc); - result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); - result->setType(*(*fields)[i].type); - } - } else - error(loc, " no such field in structure", field.c_str(), ""); } + if (fieldFound) { + if (base->getType().getQualifier().storage == EvqConst) + result = intermediate.foldDereference(base, member, loc); + else { + TConstUnionArray unionArray(1); + unionArray[0].setIConst(member); + TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc); + result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); + result->setType(*(*fields)[member].type); + } + } else + error(loc, " no such field in structure", field.c_str(), ""); } else error(loc, " dot operator does not operater on this type:", field.c_str(), base->getType().getCompleteString().c_str()); @@ -1093,7 +1065,7 @@ TFunction* TParseContext::handleConstructorCall(TSourceLoc loc, TPublicType& pub // TOperator TParseContext::mapTypeToConstructorOp(const TType& type) { - if (type.getStruct()) + if (type.isStruct()) return EOpConstructStruct; TOperator op; @@ -3102,7 +3074,7 @@ TIntermTyped* TParseContext::convertInitializerList(TSourceLoc loc, const TType& } return addConstructor(loc, initList, arrayType, mapTypeToConstructorOp(arrayType)); - } else if (type.getStruct()) { + } else if (type.isStruct()) { if (type.getStruct()->size() != initList->getSequence().size()) { error(loc, "wrong number of structure members", "initializer list", ""); return 0; @@ -3728,116 +3700,4 @@ TIntermNode* TParseContext::addSwitch(TSourceLoc loc, TIntermTyped* expression, return switchNode; } -// TODO: simplification: constant folding: these should use a fully folded model now, and probably move to Constant.cpp scheme. - -// -// Make a constant scalar or vector node, representing a given constant vector and constant swizzle into it. -// -// The type of the returned node is still the original vector type; it needs to be corrected by the caller. -// -TIntermTyped* TParseContext::addConstVectorNode(TSourceLoc loc, TVectorFields& fields, TIntermTyped* node) -{ - if (! node->getAsConstantUnion()) { - error(loc, "Cannot offset into the vector", "Error", ""); - return 0; - } - - const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray(); - TConstUnionArray constArray(fields.num); - - for (int i = 0; i < fields.num; i++) { - if (fields.offsets[i] >= node->getType().getObjectSize()) { - error(loc, "", "[", "vector index out of range '%d'", fields.offsets[i]); - fields.offsets[i] = 0; - } - - constArray[i] = unionArray[fields.offsets[i]]; - } - - return intermediate.addConstantUnion(constArray, node->getType(), loc); -} - -// -// Make a constant vector node, representing a given constant column -// from the given constant matrix. -// -// The type of the returned node is still the original matrix type; -// which needs to be corrected (dereferenced) by the caller. -// -TIntermTyped* TParseContext::addConstMatrixNode(TSourceLoc loc, int index, TIntermTyped* node) -{ - TIntermConstantUnion* constNode = node->getAsConstantUnion(); - - if (index >= node->getType().getMatrixCols()) { - error(loc, "", "[", "matrix field selection out of range '%d'", index); - index = 0; - } - - if (constNode) { - const TConstUnionArray& unionArray = constNode->getConstArray(); - int size = constNode->getType().getMatrixRows(); - return intermediate.addConstantUnion(TConstUnionArray(unionArray, size * index, size), constNode->getType(), loc); - } else { - error(loc, "Cannot offset into the matrix", "Error", ""); - return 0; - } -} - - -// -// Make a constant node, representing the constant element of the constant array. -// -// The type of the returned node is still the original array type; -// which needs to be corrected (dereferenced) by the caller. -// -TIntermTyped* TParseContext::addConstArrayNode(TSourceLoc loc, int index, TIntermTyped* node) -{ - TType arrayElementType(node->getType(), 0); // dereferenced type - - if (index >= node->getType().getArraySize() || index < 0) { - error(loc, "", "[", "array index '%d' out of range", index); - index = 0; - } - - if (node->getAsConstantUnion()) { - int arrayElementSize = arrayElementType.getObjectSize(); - return intermediate.addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), arrayElementSize * index, arrayElementSize), - node->getType(), loc); - } else { - error(loc, "Cannot offset into the array", "Error", ""); - return 0; - } -} - - -// -// This function returns the value of a particular field inside a constant structure from the symbol table. -// 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(TSourceLoc loc, TString& identifier, TIntermTyped* node) -{ - TTypeList* fields = node->getType().getStruct(); - int instanceOffset = 0; - int instanceSize; - - for (size_t index = 0; index < fields->size(); ++index) { - instanceSize = (*fields)[index].type->getObjectSize(); - - if ((*fields)[index].type->getFieldName() == identifier) - break; - - instanceOffset += instanceSize; - } - - if (node->getAsConstantUnion()) { - return intermediate.addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), instanceOffset, instanceSize), - node->getType(), loc); - // type will be changed in the calling function - } else { - error(loc, "Cannot offset into the structure", "Error", ""); - return 0; - } -} - } // end namespace glslang diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 53c0e1eb..a2ce180f 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -161,10 +161,6 @@ public: void updateTypedDefaults(TSourceLoc, const TQualifier&, const TString* id); void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); TIntermNode* addSwitch(TSourceLoc, TIntermTyped* expression, TIntermAggregate* body); - TIntermTyped* addConstVectorNode(TSourceLoc, TVectorFields&, TIntermTyped*); - TIntermTyped* addConstMatrixNode(TSourceLoc, int index, TIntermTyped*); - TIntermTyped* addConstArrayNode(TSourceLoc, int index, TIntermTyped* node); - TIntermTyped* addConstStruct(TSourceLoc, TString& , TIntermTyped*); void updateMaxArraySize(TSourceLoc, TIntermNode*, int index); diff --git a/glslang/MachineIndependent/SymbolTable.cpp b/glslang/MachineIndependent/SymbolTable.cpp index dcf84dc2..6a703249 100644 --- a/glslang/MachineIndependent/SymbolTable.cpp +++ b/glslang/MachineIndependent/SymbolTable.cpp @@ -120,7 +120,7 @@ void TType::buildMangledName(TString& mangledName) int TType::getStructSize() const { - if (!getStruct()) { + if (! isStruct()) { assert(false && "Not a struct"); return 0; } @@ -255,7 +255,7 @@ TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf) setExtensions(copyOf.numExtensions, copyOf.extensions); if (! copyOf.unionArray.empty()) { - assert(!copyOf.type.getStruct()); + assert(! copyOf.type.isStruct()); assert(copyOf.type.getObjectSize() == 1); TConstUnionArray newArray(1); newArray[0] = copyOf.unionArray[0]; diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 43177be3..5eb9d8bc 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -62,6 +62,9 @@ public: explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), numMains(0), numErrors(0), recursive(false), invocations(0), maxVertices(0), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false) { } + bool postProcess(TIntermNode*, EShLanguage); + void outputTree(TInfoSink&); + void removeTree(); void setVersion(int v) { version = v; } int getVersion() const { return version; } @@ -88,8 +91,6 @@ public: TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc); TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, TSourceLoc); bool areAllChildConst(TIntermAggregate* aggrNode); - TIntermTyped* fold(TIntermAggregate* aggrNode); - TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, TSourceLoc); TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc); TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc); @@ -101,7 +102,14 @@ public: TIntermBranch* addBranch(TOperator, TSourceLoc); TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc); TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc); - bool postProcess(TIntermNode*, EShLanguage); + + // Constant folding (in Constant.cpp) + TIntermTyped* fold(TIntermAggregate* aggrNode); + TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); + TIntermTyped* foldDereference(TIntermTyped* node, int index, TSourceLoc); + TIntermTyped* foldSwizzle(TIntermTyped* node, TVectorFields& fields, TSourceLoc); + + // Linkage related void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); @@ -147,9 +155,6 @@ public: void addIoAccessed(const TString& name) { ioAccessed.insert(name); } bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); } - void outputTree(TInfoSink&); - void removeTree(); - protected: void error(TInfoSink& infoSink, const char*); void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);