Commit 0863f0df by Nicolas Capens

Handle constant expressions that have not been constant folded.

Change-Id: I7dd1e6db9a4cee64cb10fb27373d77038b2af63e Reviewed-on: https://swiftshader-review.googlesource.com/5078Tested-by: 's avatarNicolas Capens <capn@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 3a7b29ce
...@@ -1624,7 +1624,6 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod ...@@ -1624,7 +1624,6 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
return tempNode; return tempNode;
default: default:
infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
return 0; return 0;
} }
tempNode = new TIntermConstantUnion(tempConstArray, returnType); tempNode = new TIntermConstantUnion(tempConstArray, returnType);
......
...@@ -2132,7 +2132,7 @@ namespace glsl ...@@ -2132,7 +2132,7 @@ namespace glsl
parameter.type = registerType(arg); parameter.type = registerType(arg);
parameter.bufferIndex = argumentInfo.bufferIndex; parameter.bufferIndex = argumentInfo.bufferIndex;
if(arg->getQualifier() == EvqConstExpr) if(arg->getAsConstantUnion() && arg->getAsConstantUnion()->getUnionArrayPointer())
{ {
int component = componentCount(type, argumentInfo.clampedIndex); int component = componentCount(type, argumentInfo.clampedIndex);
ConstantUnion *constants = arg->getAsConstantUnion()->getUnionArrayPointer(); ConstantUnion *constants = arg->getAsConstantUnion()->getUnionArrayPointer();
...@@ -2459,6 +2459,11 @@ namespace glsl ...@@ -2459,6 +2459,11 @@ namespace glsl
outputQualifier = qualifier; outputQualifier = qualifier;
} }
if(qualifier == EvqConstExpr && (!operand->getAsConstantUnion() || !operand->getAsConstantUnion()->getUnionArrayPointer()))
{
return sw::Shader::PARAMETER_TEMP;
}
switch(qualifier) switch(qualifier)
{ {
case EvqTemporary: return sw::Shader::PARAMETER_TEMP; case EvqTemporary: return sw::Shader::PARAMETER_TEMP;
...@@ -2510,7 +2515,7 @@ namespace glsl ...@@ -2510,7 +2515,7 @@ namespace glsl
{ {
case EvqTemporary: return temporaryRegister(operand); case EvqTemporary: return temporaryRegister(operand);
case EvqGlobal: return temporaryRegister(operand); case EvqGlobal: return temporaryRegister(operand);
case EvqConstExpr: UNREACHABLE(EvqConstExpr); case EvqConstExpr: return temporaryRegister(operand); // Unevaluated constant expression
case EvqAttribute: return attributeRegister(operand); case EvqAttribute: return attributeRegister(operand);
case EvqVaryingIn: return varyingRegister(operand); case EvqVaryingIn: return varyingRegister(operand);
case EvqVaryingOut: return varyingRegister(operand); case EvqVaryingOut: return varyingRegister(operand);
......
...@@ -228,7 +228,7 @@ void TParseContext::unaryOpError(const TSourceLoc &line, const char* op, TString ...@@ -228,7 +228,7 @@ void TParseContext::unaryOpError(const TSourceLoc &line, const char* op, TString
void TParseContext::binaryOpError(const TSourceLoc &line, const char* op, TString left, TString right) void TParseContext::binaryOpError(const TSourceLoc &line, const char* op, TString left, TString right)
{ {
std::stringstream extraInfoStream; std::stringstream extraInfoStream;
extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
<< "' and a right operand of type '" << right << "' (or there is no acceptable conversion)"; << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
std::string extraInfo = extraInfoStream.str(); std::string extraInfo = extraInfoStream.str();
error(line, " wrong operand types ", op, extraInfo.c_str()); error(line, " wrong operand types ", op, extraInfo.c_str());
...@@ -1191,11 +1191,12 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id ...@@ -1191,11 +1191,12 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id
ASSERT(intermNode != nullptr); ASSERT(intermNode != nullptr);
TType type = TType(pType); TType type = TType(pType);
TVariable *variable = nullptr;
if(type.isArray() && (type.getArraySize() == 0)) if(type.isArray() && (type.getArraySize() == 0))
{ {
type.setArraySize(initializer->getArraySize()); type.setArraySize(initializer->getArraySize());
} }
TVariable *variable = nullptr;
if(!declareVariable(line, identifier, type, &variable)) if(!declareVariable(line, identifier, type, &variable))
{ {
return true; return true;
...@@ -1218,7 +1219,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id ...@@ -1218,7 +1219,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id
// //
// identifier must be of type constant, a global, or a temporary // identifier must be of type constant, a global, or a temporary
// //
TQualifier qualifier = variable->getType().getQualifier(); TQualifier qualifier = type.getQualifier();
if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConstExpr)) { if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConstExpr)) {
error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString()); error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
return true; return true;
...@@ -1228,7 +1229,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id ...@@ -1228,7 +1229,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id
// //
if (qualifier == EvqConstExpr) { if (qualifier == EvqConstExpr) {
if (qualifier != initializer->getType().getQualifier()) { if (qualifier != initializer->getQualifier()) {
std::stringstream extraInfoStream; std::stringstream extraInfoStream;
extraInfoStream << "'" << variable->getType().getCompleteString() << "'"; extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
std::string extraInfo = extraInfoStream.str(); std::string extraInfo = extraInfoStream.str();
...@@ -1236,12 +1237,14 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id ...@@ -1236,12 +1237,14 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id
variable->getType().setQualifier(EvqTemporary); variable->getType().setQualifier(EvqTemporary);
return true; return true;
} }
if (type != initializer->getType()) { if (type != initializer->getType()) {
error(line, " non-matching types for const initializer ", error(line, " non-matching types for const initializer ",
variable->getType().getQualifierString()); variable->getType().getQualifierString());
variable->getType().setQualifier(EvqTemporary); variable->getType().setQualifier(EvqTemporary);
return true; return true;
} }
if (initializer->getAsConstantUnion()) { if (initializer->getAsConstantUnion()) {
variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
} else if (initializer->getAsSymbolNode()) { } else if (initializer->getAsSymbolNode()) {
...@@ -1250,17 +1253,10 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id ...@@ -1250,17 +1253,10 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id
ConstantUnion* constArray = tVar->getConstPointer(); ConstantUnion* constArray = tVar->getConstPointer();
variable->shareConstPointer(constArray); variable->shareConstPointer(constArray);
} else {
std::stringstream extraInfoStream;
extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
std::string extraInfo = extraInfoStream.str();
error(line, " cannot assign to", "=", extraInfo.c_str());
variable->getType().setQualifier(EvqTemporary);
return true;
} }
} }
if (qualifier != EvqConstExpr) { if (!variable->isConstant()) {
TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line); TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
*intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line); *intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
if(*intermNode == nullptr) { if(*intermNode == nullptr) {
...@@ -1273,25 +1269,6 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id ...@@ -1273,25 +1269,6 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id
return false; return false;
} }
bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
{
ASSERT(aggrNode != NULL);
if (!aggrNode->isConstructor())
return false;
bool allConstant = true;
// check if all the child nodes are constants so that they can be inserted into
// the parent node
TIntermSequence &sequence = aggrNode->getSequence() ;
for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
if (!(*p)->getAsTyped()->getAsConstantUnion())
return false;
}
return allConstant;
}
TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier) TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier)
{ {
TPublicType returnType = typeSpecifier; TPublicType returnType = typeSpecifier;
...@@ -1818,12 +1795,12 @@ TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function ...@@ -1818,12 +1795,12 @@ TIntermAggregate *TParseContext::addFunctionDefinition(const TFunction &function
aggregate->setName(function.getMangledName().c_str()); aggregate->setName(function.getMangledName().c_str());
aggregate->setType(function.getReturnType()); aggregate->setType(function.getReturnType());
// store the pragma information for debug and optimize and other vendor specific // store the pragma information for debug and optimize and other vendor specific
// information. This information can be queried from the parse tree // information. This information can be queried from the parse tree
aggregate->setOptimize(pragma().optimize); aggregate->setOptimize(pragma().optimize);
aggregate->setDebug(pragma().debug); aggregate->setDebug(pragma().debug);
if(functionBody && functionBody->getAsAggregate()) if(functionBody && functionBody->getAsAggregate())
aggregate->setEndLine(functionBody->getAsAggregate()->getEndLine()); aggregate->setEndLine(functionBody->getAsAggregate()->getEndLine());
symbolTable.pop(); symbolTable.pop();
...@@ -2117,8 +2094,8 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType* ...@@ -2117,8 +2094,8 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType*
} }
// Turn the argument list itself into a constructor // Turn the argument list itself into a constructor
TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); TIntermTyped *constConstructor = foldConstConstructor(constructor, *type);
if(constConstructor) if(constConstructor)
{ {
return constConstructor; return constConstructor;
...@@ -2129,9 +2106,8 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType* ...@@ -2129,9 +2106,8 @@ TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType*
TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
{ {
bool canBeFolded = areAllChildConst(aggrNode);
aggrNode->setType(type); aggrNode->setType(type);
if (canBeFolded) { if (aggrNode->isConstantFoldable()) {
bool returnVal = false; bool returnVal = false;
ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
if (aggrNode->getSequence().size() == 1) { if (aggrNode->getSequence().size() == 1) {
...@@ -2153,7 +2129,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co ...@@ -2153,7 +2129,7 @@ TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, co
// This function returns the tree representation for the vector field(s) being accessed from contant vector. // This function returns the tree representation for the vector field(s) being accessed from contant vector.
// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
// a constant matrix. // a constant matrix.
// //
TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc &line) TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc &line)
...@@ -2625,7 +2601,7 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre ...@@ -2625,7 +2601,7 @@ TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpre
recover(); recover();
} }
if(baseExpression->getType().getQualifier() == EvqConstExpr) if(baseExpression->getAsConstantUnion())
{ {
// constant folding for vector fields // constant folding for vector fields
indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation); indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation);
......
...@@ -143,7 +143,6 @@ public: ...@@ -143,7 +143,6 @@ public:
void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value); void handlePragmaDirective(const TSourceLoc &line, const char* name, const char* value);
bool containsSampler(TType& type); bool containsSampler(TType& type);
bool areAllChildConst(TIntermAggregate* aggrNode);
const TFunction* findFunction(const TSourceLoc &line, TFunction* pfnCall, bool *builtIn = 0); const TFunction* findFunction(const TSourceLoc &line, TFunction* pfnCall, bool *builtIn = 0);
bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType, bool executeInitializer(const TSourceLoc &line, const TString &identifier, const TPublicType &pType,
TIntermTyped *initializer, TIntermNode **intermNode); TIntermTyped *initializer, TIntermNode **intermNode);
......
...@@ -95,6 +95,7 @@ public: ...@@ -95,6 +95,7 @@ public:
} }
ConstantUnion* getConstPointer() const { return unionArray; } ConstantUnion* getConstPointer() const { return unionArray; }
bool isConstant() const { return unionArray != nullptr; }
void shareConstPointer( ConstantUnion *constArray) void shareConstPointer( ConstantUnion *constArray)
{ {
......
...@@ -217,8 +217,8 @@ variable_identifier ...@@ -217,8 +217,8 @@ variable_identifier
// don't delete $1.string, it's used by error recovery, and the pool // don't delete $1.string, it's used by error recovery, and the pool
// pop will reclaim the memory // pop will reclaim the memory
if (variable->getType().getQualifier() == EvqConstExpr ) { ConstantUnion *constArray = variable->getConstPointer();
ConstantUnion* constArray = variable->getConstPointer(); if (constArray) {
TType t(variable->getType()); TType t(variable->getType());
$$ = context->intermediate.addConstantUnion(constArray, t, @1); $$ = context->intermediate.addConstantUnion(constArray, t, @1);
} else } else
...@@ -686,7 +686,7 @@ function_header ...@@ -686,7 +686,7 @@ function_header
TType type($1); TType type($1);
function = new TFunction($2.string, type); function = new TFunction($2.string, type);
$$ = function; $$ = function;
context->symbolTable.push(); context->symbolTable.push();
} }
; ;
...@@ -914,7 +914,7 @@ type_qualifier ...@@ -914,7 +914,7 @@ type_qualifier
| interpolation_qualifier { | interpolation_qualifier {
context->error(@1, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getQualifierString($1.qualifier)); context->error(@1, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getQualifierString($1.qualifier));
context->recover(); context->recover();
TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
$$.setBasic(EbtVoid, qual, @1); $$.setBasic(EbtVoid, qual, @1);
} }
......
...@@ -2365,8 +2365,8 @@ yyreduce: ...@@ -2365,8 +2365,8 @@ yyreduce:
// don't delete $1.string, it's used by error recovery, and the pool // don't delete $1.string, it's used by error recovery, and the pool
// pop will reclaim the memory // pop will reclaim the memory
if (variable->getType().getQualifier() == EvqConstExpr ) { ConstantUnion *constArray = variable->getConstPointer();
ConstantUnion* constArray = variable->getConstPointer(); if (constArray) {
TType t(variable->getType()); TType t(variable->getType());
(yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(constArray, t, (yylsp[0])); (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(constArray, t, (yylsp[0]));
} else } else
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
// Definition of the in-memory high-level intermediate representation // Definition of the in-memory high-level intermediate representation
// of shaders. This is a tree that parser creates. // of shaders. This is a tree that parser creates.
// //
// Nodes in the tree are defined as a hierarchy of classes derived from // Nodes in the tree are defined as a hierarchy of classes derived from
// TIntermNode. Each is a node in a tree. There is no preset branching factor; // TIntermNode. Each is a node in a tree. There is no preset branching factor;
// each node can have it's own type of list of children. // each node can have it's own type of list of children.
// //
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
enum TOperator { enum TOperator {
EOpNull, // if in a node, should only mean a node is still being built EOpNull, // if in a node, should only mean a node is still being built
EOpSequence, // denotes a list of statements, or parameters, etc. EOpSequence, // denotes a list of statements, or parameters, etc.
EOpFunctionCall, EOpFunctionCall,
EOpFunction, // For function definition EOpFunction, // For function definition
EOpParameters, // an aggregate listing the parameters to a function EOpParameters, // an aggregate listing the parameters to a function
...@@ -306,7 +306,7 @@ public: ...@@ -306,7 +306,7 @@ public:
TPrecision getPrecision() const { return type.getPrecision(); } TPrecision getPrecision() const { return type.getPrecision(); }
int getNominalSize() const { return type.getNominalSize(); } int getNominalSize() const { return type.getNominalSize(); }
int getSecondarySize() const { return type.getSecondarySize(); } int getSecondarySize() const { return type.getSecondarySize(); }
bool isInterfaceBlock() const { return type.isInterfaceBlock(); } bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
bool isMatrix() const { return type.isMatrix(); } bool isMatrix() const { return type.isMatrix(); }
bool isArray() const { return type.isArray(); } bool isArray() const { return type.isArray(); }
...@@ -400,14 +400,14 @@ public: ...@@ -400,14 +400,14 @@ public:
// if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
// per process globalpoolallocator, then it causes increased memory usage per compile // per process globalpoolallocator, then it causes increased memory usage per compile
// it is essential to use "symbol = sym" to assign to symbol // it is essential to use "symbol = sym" to assign to symbol
TIntermSymbol(int i, const TString& sym, const TType& t) : TIntermSymbol(int i, const TString& sym, const TType& t) :
TIntermTyped(t), id(i) { symbol = sym; } TIntermTyped(t), id(i) { symbol = sym; }
int getId() const { return id; } int getId() const { return id; }
const TString& getSymbol() const { return symbol; } const TString& getSymbol() const { return symbol; }
void setId(int newId) { id = newId; } void setId(int newId) { id = newId; }
virtual void traverse(TIntermTraverser*); virtual void traverse(TIntermTraverser*);
virtual TIntermSymbol* getAsSymbolNode() { return this; } virtual TIntermSymbol* getAsSymbolNode() { return this; }
...@@ -418,10 +418,13 @@ protected: ...@@ -418,10 +418,13 @@ protected:
class TIntermConstantUnion : public TIntermTyped { class TIntermConstantUnion : public TIntermTyped {
public: public:
TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer)
{
getTypePointer()->setQualifier(EvqConstExpr);
}
ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
int getUConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; } int getUConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; }
float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
...@@ -452,7 +455,7 @@ public: ...@@ -452,7 +455,7 @@ public:
protected: protected:
TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
TOperator op; TOperator op;
}; };
...@@ -489,7 +492,7 @@ public: ...@@ -489,7 +492,7 @@ public:
virtual TIntermUnary* getAsUnaryNode() { return this; } virtual TIntermUnary* getAsUnaryNode() { return this; }
void setOperand(TIntermTyped* o) { operand = o; } void setOperand(TIntermTyped* o) { operand = o; }
TIntermTyped* getOperand() { return operand; } TIntermTyped* getOperand() { return operand; }
bool promote(TInfoSink&); bool promote(TInfoSink&);
protected: protected:
...@@ -527,6 +530,19 @@ public: ...@@ -527,6 +530,19 @@ public:
void setEndLine(const TSourceLoc& line) { endLine = line; } void setEndLine(const TSourceLoc& line) { endLine = line; }
const TSourceLoc& getEndLine() const { return endLine; } const TSourceLoc& getEndLine() const { return endLine; }
bool isConstantFoldable()
{
for(TIntermNode *node : sequence)
{
if(!node->getAsConstantUnion() || !node->getAsConstantUnion()->getUnionArrayPointer())
{
return false;
}
}
return true;
}
protected: protected:
TIntermAggregate(const TIntermAggregate&); // disallow copy constructor TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
...@@ -617,7 +633,7 @@ enum Visit ...@@ -617,7 +633,7 @@ enum Visit
}; };
// //
// For traversing the tree. User should derive from this, // For traversing the tree. User should derive from this,
// put their traversal specific data in it, and then pass // put their traversal specific data in it, and then pass
// it to a Traverse method. // it to a Traverse method.
// //
...@@ -628,7 +644,7 @@ class TIntermTraverser ...@@ -628,7 +644,7 @@ class TIntermTraverser
{ {
public: public:
POOL_ALLOCATOR_NEW_DELETE(); POOL_ALLOCATOR_NEW_DELETE();
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
preVisit(preVisit), preVisit(preVisit),
inVisit(inVisit), inVisit(inVisit),
postVisit(postVisit), postVisit(postVisit),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment