Simplify and rationalize constant folding for dereferences (array, matrix, vector, swizzle, struct).
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24259 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
1fbaa35ce7
commit
3591813a8b
@ -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
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
//
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user