Improvement to the AST traversal infrastructure.
Note: This affects any downstream consumers of glslang's traverser. Let me know if there are any issues. Essentially, you will need to change the functions that were pointed to into overriding base-class members instead. See the examples in this check in. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24740 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
4f9aebf659
commit
a9819921b3
@ -643,6 +643,13 @@ protected:
|
|||||||
TIntermAggregate* body;
|
TIntermAggregate* body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum TVisit
|
||||||
|
{
|
||||||
|
EvPreVisit,
|
||||||
|
EvInVisit,
|
||||||
|
EvPostVisit
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// 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
|
||||||
@ -653,43 +660,65 @@ protected:
|
|||||||
//
|
//
|
||||||
// Explicitly set postVisit to true if you want post visiting, otherwise,
|
// Explicitly set postVisit to true if you want post visiting, otherwise,
|
||||||
// filled in methods will only be called at pre-visit time (before processing
|
// filled in methods will only be called at pre-visit time (before processing
|
||||||
// the subtree).
|
// the subtree). Similary for inVisit for in-order visiting of nodes with
|
||||||
|
// multiple children.
|
||||||
//
|
//
|
||||||
// If you only want post-visits, explicitly turn off preVisit and turn on postVisit.
|
// If you only want post-visits, explicitly turn off preVisit (and inVisit)
|
||||||
|
// and turn on postVisit.
|
||||||
//
|
//
|
||||||
class TIntermTraverser {
|
class TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
|
||||||
|
TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
|
||||||
|
preVisit(preVisit),
|
||||||
|
inVisit(inVisit),
|
||||||
|
postVisit(postVisit),
|
||||||
|
rightToLeft(rightToLeft),
|
||||||
|
depth(0),
|
||||||
|
maxDepth(0) { }
|
||||||
|
virtual ~TIntermTraverser() { }
|
||||||
|
|
||||||
TIntermTraverser() :
|
virtual void visitSymbol(TIntermSymbol*) { }
|
||||||
visitSymbol(0),
|
virtual void visitConstantUnion(TIntermConstantUnion*) { }
|
||||||
visitConstantUnion(0),
|
virtual bool visitBinary(TVisit visit, TIntermBinary*) { return true; }
|
||||||
visitBinary(0),
|
virtual bool visitUnary(TVisit visit, TIntermUnary*) { return true; }
|
||||||
visitUnary(0),
|
virtual bool visitSelection(TVisit visit, TIntermSelection*) { return true; }
|
||||||
visitSelection(0),
|
virtual bool visitAggregate(TVisit visit, TIntermAggregate*) { return true; }
|
||||||
visitAggregate(0),
|
virtual bool visitLoop(TVisit visit, TIntermLoop*) { return true; }
|
||||||
visitLoop(0),
|
virtual bool visitBranch(TVisit visit, TIntermBranch*) { return true; }
|
||||||
visitBranch(0),
|
virtual bool visitSwitch(TVisit, TIntermSwitch* node) { return true; }
|
||||||
visitSwitch(0),
|
|
||||||
depth(0),
|
|
||||||
preVisit(true),
|
|
||||||
postVisit(false),
|
|
||||||
rightToLeft(false) {}
|
|
||||||
|
|
||||||
void (*visitSymbol)(TIntermSymbol*, TIntermTraverser*);
|
int getMaxDepth() const { return maxDepth; }
|
||||||
void (*visitConstantUnion)(TIntermConstantUnion*, TIntermTraverser*);
|
|
||||||
bool (*visitBinary)(bool preVisit, TIntermBinary*, TIntermTraverser*);
|
|
||||||
bool (*visitUnary)(bool preVisit, TIntermUnary*, TIntermTraverser*);
|
|
||||||
bool (*visitSelection)(bool preVisit, TIntermSelection*, TIntermTraverser*);
|
|
||||||
bool (*visitAggregate)(bool preVisit, TIntermAggregate*, TIntermTraverser*);
|
|
||||||
bool (*visitLoop)(bool preVisit, TIntermLoop*, TIntermTraverser*);
|
|
||||||
bool (*visitBranch)(bool preVisit, TIntermBranch*, TIntermTraverser*);
|
|
||||||
bool (*visitSwitch)(bool preVisit, TIntermSwitch*, TIntermTraverser*);
|
|
||||||
|
|
||||||
int depth;
|
void incrementDepth(TIntermNode *current)
|
||||||
bool preVisit;
|
{
|
||||||
bool postVisit;
|
depth++;
|
||||||
bool rightToLeft;
|
maxDepth = std::max(maxDepth, depth);
|
||||||
|
path.push_back(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
void decrementDepth()
|
||||||
|
{
|
||||||
|
depth--;
|
||||||
|
path.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
TIntermNode *getParentNode()
|
||||||
|
{
|
||||||
|
return path.size() == 0 ? NULL : path.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool preVisit;
|
||||||
|
const bool inVisit;
|
||||||
|
const bool postVisit;
|
||||||
|
const bool rightToLeft;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int depth;
|
||||||
|
int maxDepth;
|
||||||
|
|
||||||
|
// All the nodes from root to the current node's parent during traversing.
|
||||||
|
TVector<TIntermNode *> path;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace glslang
|
} // end namespace glslang
|
||||||
|
|||||||
@ -9,5 +9,5 @@
|
|||||||
// source have to figure out how to create revision.h just to get a build
|
// source have to figure out how to create revision.h just to get a build
|
||||||
// going. However, if it is not updated, it can be a version behind.
|
// going. However, if it is not updated, it can be a version behind.
|
||||||
|
|
||||||
#define GLSLANG_REVISION "24692"
|
#define GLSLANG_REVISION "24738"
|
||||||
#define GLSLANG_DATE "2014/01/08 16:25:18"
|
#define GLSLANG_DATE "2014/01/10 14:25:05"
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
//
|
//
|
||||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||||
//Copyright (C) 2013 LunarG, Inc.
|
//Copyright (C) 2013 LunarG, Inc.
|
||||||
|
//Copyright (c) 2002-2010 The ANGLE Project Authors.
|
||||||
//
|
//
|
||||||
//All rights reserved.
|
//All rights reserved.
|
||||||
//
|
//
|
||||||
@ -62,122 +63,138 @@ void TIntermMethod::traverse(TIntermTraverser* it)
|
|||||||
// TODO: 4.3 functionality: some .length() will stay as methods
|
// TODO: 4.3 functionality: some .length() will stay as methods
|
||||||
}
|
}
|
||||||
|
|
||||||
void TIntermSymbol::traverse(TIntermTraverser* it)
|
void TIntermSymbol::traverse(TIntermTraverser *it)
|
||||||
{
|
{
|
||||||
if (it->visitSymbol)
|
it->visitSymbol(this);
|
||||||
it->visitSymbol(this, it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TIntermConstantUnion::traverse(TIntermTraverser* it)
|
void TIntermConstantUnion::traverse(TIntermTraverser *it)
|
||||||
{
|
{
|
||||||
if (it->visitConstantUnion)
|
it->visitConstantUnion(this);
|
||||||
it->visitConstantUnion(this, it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Traverse a binary node.
|
// Traverse a binary node.
|
||||||
//
|
//
|
||||||
void TIntermBinary::traverse(TIntermTraverser* it)
|
void TIntermBinary::traverse(TIntermTraverser *it)
|
||||||
{
|
{
|
||||||
bool visit = true;
|
bool visit = true;
|
||||||
|
|
||||||
//
|
//
|
||||||
// visit the node before children if pre-visiting.
|
// visit the node before children if pre-visiting.
|
||||||
//
|
//
|
||||||
if (it->preVisit && it->visitBinary)
|
if (it->preVisit)
|
||||||
visit = it->visitBinary(true, this, it);
|
visit = it->visitBinary(EvPreVisit, this);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Visit the children, in the right order.
|
// Visit the children, in the right order.
|
||||||
//
|
//
|
||||||
if (visit) {
|
if (visit) {
|
||||||
++it->depth;
|
it->incrementDepth(this);
|
||||||
|
|
||||||
if (it->rightToLeft) {
|
if (it->rightToLeft) {
|
||||||
if (right)
|
if (right)
|
||||||
right->traverse(it);
|
right->traverse(it);
|
||||||
if (left)
|
|
||||||
|
if (it->inVisit)
|
||||||
|
visit = it->visitBinary(EvInVisit, this);
|
||||||
|
|
||||||
|
if (visit && left)
|
||||||
left->traverse(it);
|
left->traverse(it);
|
||||||
} else {
|
} else {
|
||||||
if (left)
|
if (left)
|
||||||
left->traverse(it);
|
left->traverse(it);
|
||||||
if (right)
|
|
||||||
|
if (it->inVisit)
|
||||||
|
visit = it->visitBinary(EvInVisit, this);
|
||||||
|
|
||||||
|
if (visit && right)
|
||||||
right->traverse(it);
|
right->traverse(it);
|
||||||
}
|
}
|
||||||
--it->depth;
|
|
||||||
|
it->decrementDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Visit the node after the children, if requested and the traversal
|
// Visit the node after the children, if requested and the traversal
|
||||||
// hasn't been cancelled yet.
|
// hasn't been cancelled yet.
|
||||||
//
|
//
|
||||||
if (visit && it->postVisit && it->visitBinary)
|
if (visit && it->postVisit)
|
||||||
it->visitBinary(false, this, it);
|
it->visitBinary(EvPostVisit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Traverse a unary node. Same comments in binary node apply here.
|
// Traverse a unary node. Same comments in binary node apply here.
|
||||||
//
|
//
|
||||||
void TIntermUnary::traverse(TIntermTraverser* it)
|
void TIntermUnary::traverse(TIntermTraverser *it)
|
||||||
{
|
{
|
||||||
bool visit = true;
|
bool visit = true;
|
||||||
|
|
||||||
if (it->preVisit && it->visitUnary)
|
if (it->preVisit)
|
||||||
visit = it->visitUnary(true, this, it);
|
visit = it->visitUnary(EvPreVisit, this);
|
||||||
|
|
||||||
if (visit) {
|
if (visit) {
|
||||||
++it->depth;
|
it->incrementDepth(this);
|
||||||
operand->traverse(it);
|
operand->traverse(it);
|
||||||
--it->depth;
|
it->decrementDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visit && it->postVisit && it->visitUnary)
|
if (visit && it->postVisit)
|
||||||
it->visitUnary(false, this, it);
|
it->visitUnary(EvPostVisit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Traverse an aggregate node. Same comments in binary node apply here.
|
// Traverse an aggregate node. Same comments in binary node apply here.
|
||||||
//
|
//
|
||||||
void TIntermAggregate::traverse(TIntermTraverser* it)
|
void TIntermAggregate::traverse(TIntermTraverser *it)
|
||||||
{
|
{
|
||||||
bool visit = true;
|
bool visit = true;
|
||||||
|
|
||||||
if (it->preVisit && it->visitAggregate)
|
|
||||||
visit = it->visitAggregate(true, this, it);
|
|
||||||
|
|
||||||
if (visit) {
|
|
||||||
++it->depth;
|
|
||||||
|
|
||||||
TIntermSequence::iterator sit;
|
if (it->preVisit)
|
||||||
|
visit = it->visitAggregate(EvPreVisit, this);
|
||||||
|
|
||||||
|
if (visit) {
|
||||||
|
it->incrementDepth(this);
|
||||||
|
|
||||||
if (it->rightToLeft) {
|
if (it->rightToLeft) {
|
||||||
sit = sequence.end();
|
for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) {
|
||||||
while (sit != sequence.begin()) {
|
|
||||||
--sit;
|
|
||||||
(*sit)->traverse(it);
|
(*sit)->traverse(it);
|
||||||
|
|
||||||
|
if (visit && it->inVisit) {
|
||||||
|
if (*sit != sequence.front())
|
||||||
|
visit = it->visitAggregate(EvInVisit, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (sit = sequence.begin(); sit != sequence.end(); ++sit)
|
for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) {
|
||||||
(*sit)->traverse(it);
|
(*sit)->traverse(it);
|
||||||
|
|
||||||
|
if (visit && it->inVisit) {
|
||||||
|
if (*sit != sequence.back())
|
||||||
|
visit = it->visitAggregate(EvInVisit, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
--it->depth;
|
it->decrementDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visit && it->postVisit && it->visitAggregate)
|
if (visit && it->postVisit)
|
||||||
it->visitAggregate(false, this, it);
|
it->visitAggregate(EvPostVisit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Traverse a selection node. Same comments in binary node apply here.
|
// Traverse a selection node. Same comments in binary node apply here.
|
||||||
//
|
//
|
||||||
void TIntermSelection::traverse(TIntermTraverser* it)
|
void TIntermSelection::traverse(TIntermTraverser *it)
|
||||||
{
|
{
|
||||||
bool visit = true;
|
bool visit = true;
|
||||||
|
|
||||||
if (it->preVisit && it->visitSelection)
|
if (it->preVisit)
|
||||||
visit = it->visitSelection(true, this, it);
|
visit = it->visitSelection(EvPreVisit, this);
|
||||||
|
|
||||||
if (visit) {
|
if (visit) {
|
||||||
++it->depth;
|
it->incrementDepth(this);
|
||||||
if (it->rightToLeft) {
|
if (it->rightToLeft) {
|
||||||
if (falseBlock)
|
if (falseBlock)
|
||||||
falseBlock->traverse(it);
|
falseBlock->traverse(it);
|
||||||
@ -191,65 +208,71 @@ void TIntermSelection::traverse(TIntermTraverser* it)
|
|||||||
if (falseBlock)
|
if (falseBlock)
|
||||||
falseBlock->traverse(it);
|
falseBlock->traverse(it);
|
||||||
}
|
}
|
||||||
--it->depth;
|
it->decrementDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visit && it->postVisit && it->visitSelection)
|
if (visit && it->postVisit)
|
||||||
it->visitSelection(false, this, it);
|
it->visitSelection(EvPostVisit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Traverse a loop node. Same comments in binary node apply here.
|
// Traverse a loop node. Same comments in binary node apply here.
|
||||||
//
|
//
|
||||||
void TIntermLoop::traverse(TIntermTraverser* it)
|
void TIntermLoop::traverse(TIntermTraverser *it)
|
||||||
{
|
{
|
||||||
bool visit = true;
|
bool visit = true;
|
||||||
|
|
||||||
if (it->preVisit && it->visitLoop)
|
if (it->preVisit)
|
||||||
visit = it->visitLoop(true, this, it);
|
visit = it->visitLoop(EvPreVisit, this);
|
||||||
|
|
||||||
if (visit) {
|
if (visit) {
|
||||||
++it->depth;
|
it->incrementDepth(this);
|
||||||
|
|
||||||
if (it->rightToLeft) {
|
if (it->rightToLeft) {
|
||||||
if (terminal)
|
if (terminal)
|
||||||
terminal->traverse(it);
|
terminal->traverse(it);
|
||||||
|
|
||||||
if (body)
|
if (body)
|
||||||
body->traverse(it);
|
body->traverse(it);
|
||||||
|
|
||||||
if (test)
|
if (test)
|
||||||
test->traverse(it);
|
test->traverse(it);
|
||||||
} else {
|
} else {
|
||||||
if (test)
|
if (test)
|
||||||
test->traverse(it);
|
test->traverse(it);
|
||||||
|
|
||||||
if (body)
|
if (body)
|
||||||
body->traverse(it);
|
body->traverse(it);
|
||||||
|
|
||||||
if (terminal)
|
if (terminal)
|
||||||
terminal->traverse(it);
|
terminal->traverse(it);
|
||||||
}
|
}
|
||||||
--it->depth;
|
|
||||||
|
it->decrementDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visit && it->postVisit && it->visitLoop)
|
if (visit && it->postVisit)
|
||||||
it->visitLoop(false, this, it);
|
it->visitLoop(EvPostVisit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Traverse a branch node. Same comments in binary node apply here.
|
// Traverse a branch node. Same comments in binary node apply here.
|
||||||
//
|
//
|
||||||
void TIntermBranch::traverse(TIntermTraverser* it)
|
void TIntermBranch::traverse(TIntermTraverser *it)
|
||||||
{
|
{
|
||||||
bool visit = true;
|
bool visit = true;
|
||||||
|
|
||||||
if (it->preVisit && it->visitBranch)
|
if (it->preVisit)
|
||||||
visit = it->visitBranch(true, this, it);
|
visit = it->visitBranch(EvPreVisit, this);
|
||||||
|
|
||||||
if (visit && expression) {
|
if (visit && expression) {
|
||||||
++it->depth;
|
it->incrementDepth(this);
|
||||||
expression->traverse(it);
|
expression->traverse(it);
|
||||||
--it->depth;
|
it->decrementDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visit && it->postVisit && it->visitBranch)
|
if (visit && it->postVisit)
|
||||||
it->visitBranch(false, this, it);
|
it->visitBranch(EvPostVisit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -259,11 +282,11 @@ void TIntermSwitch::traverse(TIntermTraverser* it)
|
|||||||
{
|
{
|
||||||
bool visit = true;
|
bool visit = true;
|
||||||
|
|
||||||
if (it->preVisit && it->visitSwitch)
|
if (it->preVisit)
|
||||||
visit = it->visitSwitch(true, this, it);
|
visit = it->visitSwitch(EvPreVisit, this);
|
||||||
|
|
||||||
if (visit) {
|
if (visit) {
|
||||||
++it->depth;
|
it->incrementDepth(this);
|
||||||
if (it->rightToLeft) {
|
if (it->rightToLeft) {
|
||||||
body->traverse(it);
|
body->traverse(it);
|
||||||
condition->traverse(it);
|
condition->traverse(it);
|
||||||
@ -271,11 +294,11 @@ void TIntermSwitch::traverse(TIntermTraverser* it)
|
|||||||
condition->traverse(it);
|
condition->traverse(it);
|
||||||
body->traverse(it);
|
body->traverse(it);
|
||||||
}
|
}
|
||||||
--it->depth;
|
it->decrementDepth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visit && it->postVisit && it->visitSwitch)
|
if (visit && it->postVisit)
|
||||||
it->visitSwitch(false, this, it);
|
it->visitSwitch(EvPostVisit, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end namespace glslang
|
} // end namespace glslang
|
||||||
|
|||||||
@ -42,85 +42,75 @@ namespace glslang {
|
|||||||
//
|
//
|
||||||
// Code to recursively delete the intermediate tree.
|
// Code to recursively delete the intermediate tree.
|
||||||
//
|
//
|
||||||
|
struct TRemoveTraverser : TIntermTraverser {
|
||||||
|
TRemoveTraverser() : TIntermTraverser(false, false, true, false) {}
|
||||||
|
|
||||||
void RemoveSymbol(TIntermSymbol* node, TIntermTraverser* it)
|
virtual void visitSymbol(TIntermSymbol* node)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveBinary(bool /*preVisit*/ , TIntermBinary* node, TIntermTraverser*)
|
virtual bool visitBinary(TVisit /* visit*/ , TIntermBinary* node)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveUnary(bool /*preVisit */, TIntermUnary* node, TIntermTraverser*)
|
virtual bool visitUnary(TVisit /* visit */, TIntermUnary* node)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveAggregate(bool /*preVisit*/ , TIntermAggregate* node, TIntermTraverser*)
|
virtual bool visitAggregate(TVisit /* visit*/ , TIntermAggregate* node)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveSelection(bool /*preVisit*/ , TIntermSelection* node, TIntermTraverser*)
|
virtual bool visitSelection(TVisit /* visit*/ , TIntermSelection* node)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveSwitch(bool /*preVisit*/ , TIntermSwitch* node, TIntermTraverser*)
|
virtual bool visitSwitch(TVisit /* visit*/ , TIntermSwitch* node)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveConstantUnion(TIntermConstantUnion* node, TIntermTraverser*)
|
virtual void visitConstantUnion(TIntermConstantUnion* node)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveLoop(bool /*preVisit*/ , TIntermLoop* node, TIntermTraverser*)
|
virtual bool visitLoop(TVisit /* visit*/ , TIntermLoop* node)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveBranch(bool /*preVisit*/ , TIntermBranch* node, TIntermTraverser*)
|
virtual bool visitBranch(TVisit /* visit*/ , TIntermBranch* node)
|
||||||
{
|
{
|
||||||
delete node;
|
delete node;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Entry point.
|
// Entry point.
|
||||||
//
|
//
|
||||||
void RemoveAllTreeNodes(TIntermNode* root)
|
void RemoveAllTreeNodes(TIntermNode* root)
|
||||||
{
|
{
|
||||||
TIntermTraverser it;
|
TRemoveTraverser it;
|
||||||
|
|
||||||
it.visitSymbol = RemoveSymbol;
|
|
||||||
it.visitConstantUnion = RemoveConstantUnion;
|
|
||||||
it.visitBinary = RemoveBinary;
|
|
||||||
it.visitUnary = RemoveUnary;
|
|
||||||
it.visitAggregate = RemoveAggregate;
|
|
||||||
it.visitSelection = RemoveSelection;
|
|
||||||
it.visitLoop = RemoveLoop;
|
|
||||||
it.visitBranch = RemoveBranch;
|
|
||||||
it.visitSwitch = RemoveSwitch;
|
|
||||||
|
|
||||||
it.preVisit = false;
|
|
||||||
it.postVisit = true;
|
|
||||||
|
|
||||||
root->traverse(&it);
|
root->traverse(&it);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,6 +55,17 @@ namespace glslang {
|
|||||||
class TOutputTraverser : public TIntermTraverser {
|
class TOutputTraverser : public TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
TOutputTraverser(TInfoSink& i) : infoSink(i) { }
|
TOutputTraverser(TInfoSink& i) : infoSink(i) { }
|
||||||
|
|
||||||
|
virtual bool visitBinary(TVisit, TIntermBinary* node);
|
||||||
|
virtual bool visitUnary(TVisit, TIntermUnary* node);
|
||||||
|
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
||||||
|
virtual bool visitSelection(TVisit, TIntermSelection* node);
|
||||||
|
virtual void visitConstantUnion(TIntermConstantUnion* node);
|
||||||
|
virtual void visitSymbol(TIntermSymbol* node);
|
||||||
|
virtual bool visitLoop(TVisit, TIntermLoop* node);
|
||||||
|
virtual bool visitBranch(TVisit, TIntermBranch* node);
|
||||||
|
virtual bool visitSwitch(TVisit, TIntermSwitch* node);
|
||||||
|
|
||||||
TInfoSink& infoSink;
|
TInfoSink& infoSink;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -85,12 +96,11 @@ void OutputTreeText(TInfoSink& infoSink, const TIntermNode* node, const int dept
|
|||||||
// return false.
|
// return false.
|
||||||
//
|
//
|
||||||
|
|
||||||
bool OutputBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
bool TOutputTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
|
||||||
{
|
{
|
||||||
TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
|
TInfoSink& out = infoSink;
|
||||||
TInfoSink& out = oit->infoSink;
|
|
||||||
|
|
||||||
OutputTreeText(out, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
|
|
||||||
switch (node->getOp()) {
|
switch (node->getOp()) {
|
||||||
case EOpAssign: out.debug << "move second child to first child"; break;
|
case EOpAssign: out.debug << "move second child to first child"; break;
|
||||||
@ -152,12 +162,11 @@ bool OutputBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OutputUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
|
bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
|
||||||
{
|
{
|
||||||
TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
|
TInfoSink& out = infoSink;
|
||||||
TInfoSink& out = oit->infoSink;
|
|
||||||
|
|
||||||
OutputTreeText(out, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
|
|
||||||
switch (node->getOp()) {
|
switch (node->getOp()) {
|
||||||
case EOpNegative: out.debug << "Negate value"; break;
|
case EOpNegative: out.debug << "Negate value"; break;
|
||||||
@ -261,17 +270,16 @@ bool OutputUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
|
bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
||||||
{
|
{
|
||||||
TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
|
TInfoSink& out = infoSink;
|
||||||
TInfoSink& out = oit->infoSink;
|
|
||||||
|
|
||||||
if (node->getOp() == EOpNull) {
|
if (node->getOp() == EOpNull) {
|
||||||
out.debug.message(EPrefixError, "node is still EOpNull!");
|
out.debug.message(EPrefixError, "node is still EOpNull!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputTreeText(out, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
|
|
||||||
switch (node->getOp()) {
|
switch (node->getOp()) {
|
||||||
case EOpSequence: out.debug << "Sequence\n"; return true;
|
case EOpSequence: out.debug << "Sequence\n"; return true;
|
||||||
@ -368,36 +376,35 @@ bool OutputAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTravers
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OutputSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
|
bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node)
|
||||||
{
|
{
|
||||||
TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
|
TInfoSink& out = infoSink;
|
||||||
TInfoSink& out = oit->infoSink;
|
|
||||||
|
|
||||||
OutputTreeText(out, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
|
|
||||||
out.debug << "Test condition and select";
|
out.debug << "Test condition and select";
|
||||||
out.debug << " (" << node->getCompleteString() << ")\n";
|
out.debug << " (" << node->getCompleteString() << ")\n";
|
||||||
|
|
||||||
++oit->depth;
|
++depth;
|
||||||
|
|
||||||
OutputTreeText(oit->infoSink, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
out.debug << "Condition\n";
|
out.debug << "Condition\n";
|
||||||
node->getCondition()->traverse(it);
|
node->getCondition()->traverse(this);
|
||||||
|
|
||||||
OutputTreeText(oit->infoSink, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
if (node->getTrueBlock()) {
|
if (node->getTrueBlock()) {
|
||||||
out.debug << "true case\n";
|
out.debug << "true case\n";
|
||||||
node->getTrueBlock()->traverse(it);
|
node->getTrueBlock()->traverse(this);
|
||||||
} else
|
} else
|
||||||
out.debug << "true case is null\n";
|
out.debug << "true case is null\n";
|
||||||
|
|
||||||
if (node->getFalseBlock()) {
|
if (node->getFalseBlock()) {
|
||||||
OutputTreeText(oit->infoSink, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
out.debug << "false case\n";
|
out.debug << "false case\n";
|
||||||
node->getFalseBlock()->traverse(it);
|
node->getFalseBlock()->traverse(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
--oit->depth;
|
--depth;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -454,78 +461,72 @@ void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const TConstU
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
|
void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
||||||
{
|
{
|
||||||
TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
|
OutputTreeText(infoSink, node, depth);
|
||||||
|
infoSink.debug << "Constant:\n";
|
||||||
|
|
||||||
OutputTreeText(oit->infoSink, node, oit->depth);
|
OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1);
|
||||||
oit->infoSink.debug << "Constant:\n";
|
|
||||||
|
|
||||||
OutputConstantUnion(oit->infoSink, node, node->getConstArray(), oit->depth + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputSymbol(TIntermSymbol* node, TIntermTraverser* it)
|
void TOutputTraverser::visitSymbol(TIntermSymbol* node)
|
||||||
{
|
{
|
||||||
TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
|
OutputTreeText(infoSink, node, depth);
|
||||||
|
|
||||||
OutputTreeText(oit->infoSink, node, oit->depth);
|
|
||||||
|
|
||||||
const int maxSize = GlslangMaxTypeLength + GlslangMaxTokenLength;
|
const int maxSize = GlslangMaxTypeLength + GlslangMaxTokenLength;
|
||||||
char buf[maxSize];
|
char buf[maxSize];
|
||||||
snprintf(buf, maxSize, "'%s' (%s)\n",
|
snprintf(buf, maxSize, "'%s' (%s)\n",
|
||||||
node->getName().c_str(),
|
node->getName().c_str(),
|
||||||
node->getCompleteString().c_str());
|
node->getCompleteString().c_str());
|
||||||
oit->infoSink.debug << buf;
|
infoSink.debug << buf;
|
||||||
|
|
||||||
if (! node->getConstArray().empty())
|
if (! node->getConstArray().empty())
|
||||||
OutputConstantUnion(oit->infoSink, node, node->getConstArray(), oit->depth + 1);
|
OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OutputLoop(bool /* preVisit */, TIntermLoop* node, TIntermTraverser* it)
|
bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node)
|
||||||
{
|
{
|
||||||
TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
|
TInfoSink& out = infoSink;
|
||||||
TInfoSink& out = oit->infoSink;
|
|
||||||
|
|
||||||
OutputTreeText(out, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
|
|
||||||
out.debug << "Loop with condition ";
|
out.debug << "Loop with condition ";
|
||||||
if (! node->testFirst())
|
if (! node->testFirst())
|
||||||
out.debug << "not ";
|
out.debug << "not ";
|
||||||
out.debug << "tested first\n";
|
out.debug << "tested first\n";
|
||||||
|
|
||||||
++oit->depth;
|
++depth;
|
||||||
|
|
||||||
OutputTreeText(oit->infoSink, node, oit->depth);
|
OutputTreeText(infoSink, node, depth);
|
||||||
if (node->getTest()) {
|
if (node->getTest()) {
|
||||||
out.debug << "Loop Condition\n";
|
out.debug << "Loop Condition\n";
|
||||||
node->getTest()->traverse(it);
|
node->getTest()->traverse(this);
|
||||||
} else
|
} else
|
||||||
out.debug << "No loop condition\n";
|
out.debug << "No loop condition\n";
|
||||||
|
|
||||||
OutputTreeText(oit->infoSink, node, oit->depth);
|
OutputTreeText(infoSink, node, depth);
|
||||||
if (node->getBody()) {
|
if (node->getBody()) {
|
||||||
out.debug << "Loop Body\n";
|
out.debug << "Loop Body\n";
|
||||||
node->getBody()->traverse(it);
|
node->getBody()->traverse(this);
|
||||||
} else
|
} else
|
||||||
out.debug << "No loop body\n";
|
out.debug << "No loop body\n";
|
||||||
|
|
||||||
if (node->getTerminal()) {
|
if (node->getTerminal()) {
|
||||||
OutputTreeText(oit->infoSink, node, oit->depth);
|
OutputTreeText(infoSink, node, depth);
|
||||||
out.debug << "Loop Terminal Expression\n";
|
out.debug << "Loop Terminal Expression\n";
|
||||||
node->getTerminal()->traverse(it);
|
node->getTerminal()->traverse(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
--oit->depth;
|
--depth;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OutputBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
|
bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node)
|
||||||
{
|
{
|
||||||
TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
|
TInfoSink& out = infoSink;
|
||||||
TInfoSink& out = oit->infoSink;
|
|
||||||
|
|
||||||
OutputTreeText(out, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
|
|
||||||
switch (node->getFlowOp()) {
|
switch (node->getFlowOp()) {
|
||||||
case EOpKill: out.debug << "Branch: Kill"; break;
|
case EOpKill: out.debug << "Branch: Kill"; break;
|
||||||
@ -539,35 +540,34 @@ bool OutputBranch(bool /* previsit*/, TIntermBranch* node, TIntermTraverser* it)
|
|||||||
|
|
||||||
if (node->getExpression()) {
|
if (node->getExpression()) {
|
||||||
out.debug << " with expression\n";
|
out.debug << " with expression\n";
|
||||||
++oit->depth;
|
++depth;
|
||||||
node->getExpression()->traverse(it);
|
node->getExpression()->traverse(this);
|
||||||
--oit->depth;
|
--depth;
|
||||||
} else
|
} else
|
||||||
out.debug << "\n";
|
out.debug << "\n";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OutputSwitch(bool /* preVisit */, TIntermSwitch* node, TIntermTraverser* it)
|
bool TOutputTraverser::visitSwitch(TVisit /* visit */, TIntermSwitch* node)
|
||||||
{
|
{
|
||||||
TOutputTraverser* oit = static_cast<TOutputTraverser*>(it);
|
TInfoSink& out = infoSink;
|
||||||
TInfoSink& out = oit->infoSink;
|
|
||||||
|
|
||||||
OutputTreeText(out, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
out.debug << "switch\n";
|
out.debug << "switch\n";
|
||||||
|
|
||||||
OutputTreeText(out, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
out.debug << "condition\n";
|
out.debug << "condition\n";
|
||||||
++oit->depth;
|
++depth;
|
||||||
node->getCondition()->traverse(it);
|
node->getCondition()->traverse(this);
|
||||||
|
|
||||||
--oit->depth;
|
--depth;
|
||||||
OutputTreeText(out, node, oit->depth);
|
OutputTreeText(out, node, depth);
|
||||||
out.debug << "body\n";
|
out.debug << "body\n";
|
||||||
++oit->depth;
|
++depth;
|
||||||
node->getBody()->traverse(it);
|
node->getBody()->traverse(this);
|
||||||
|
|
||||||
--oit->depth;
|
--depth;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -621,16 +621,6 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
|
|||||||
|
|
||||||
TOutputTraverser it(infoSink);
|
TOutputTraverser it(infoSink);
|
||||||
|
|
||||||
it.visitAggregate = OutputAggregate;
|
|
||||||
it.visitBinary = OutputBinary;
|
|
||||||
it.visitConstantUnion = OutputConstantUnion;
|
|
||||||
it.visitSelection = OutputSelection;
|
|
||||||
it.visitSymbol = OutputSymbol;
|
|
||||||
it.visitUnary = OutputUnary;
|
|
||||||
it.visitLoop = OutputLoop;
|
|
||||||
it.visitBranch = OutputBranch;
|
|
||||||
it.visitSwitch = OutputSwitch;
|
|
||||||
|
|
||||||
treeRoot->traverse(&it);
|
treeRoot->traverse(&it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -63,7 +63,13 @@ namespace glslang {
|
|||||||
|
|
||||||
class TInductiveTraverser : public TIntermTraverser {
|
class TInductiveTraverser : public TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
TInductiveTraverser(int id, TSymbolTable& st) : loopId(id), symbolTable(st), bad(false) { }
|
TInductiveTraverser(int id, TSymbolTable& st)
|
||||||
|
: loopId(id), symbolTable(st), bad(false) { }
|
||||||
|
|
||||||
|
virtual bool visitBinary(TVisit, TIntermBinary* node);
|
||||||
|
virtual bool visitUnary(TVisit, TIntermUnary* node);
|
||||||
|
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
||||||
|
|
||||||
int loopId; // unique ID of the symbol that's the loop inductive variable
|
int loopId; // unique ID of the symbol that's the loop inductive variable
|
||||||
TSymbolTable& symbolTable;
|
TSymbolTable& symbolTable;
|
||||||
bool bad;
|
bool bad;
|
||||||
@ -71,49 +77,43 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// check binary operations for those modifying the loop index
|
// check binary operations for those modifying the loop index
|
||||||
bool InductiveBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
bool TInductiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
|
||||||
{
|
{
|
||||||
TInductiveTraverser* oit = static_cast<TInductiveTraverser*>(it);
|
|
||||||
|
|
||||||
if (node->modifiesState() && node->getLeft()->getAsSymbolNode() &&
|
if (node->modifiesState() && node->getLeft()->getAsSymbolNode() &&
|
||||||
node->getLeft()->getAsSymbolNode()->getId() == oit->loopId) {
|
node->getLeft()->getAsSymbolNode()->getId() == loopId) {
|
||||||
oit->bad = true;
|
bad = true;
|
||||||
oit->badLoc = node->getLoc();
|
badLoc = node->getLoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check unary operations for those modifying the loop index
|
// check unary operations for those modifying the loop index
|
||||||
bool InductiveUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
|
bool TInductiveTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
|
||||||
{
|
{
|
||||||
TInductiveTraverser* oit = static_cast<TInductiveTraverser*>(it);
|
|
||||||
|
|
||||||
if (node->modifiesState() && node->getOperand()->getAsSymbolNode() &&
|
if (node->modifiesState() && node->getOperand()->getAsSymbolNode() &&
|
||||||
node->getOperand()->getAsSymbolNode()->getId() == oit->loopId) {
|
node->getOperand()->getAsSymbolNode()->getId() == loopId) {
|
||||||
oit->bad = true;
|
bad = true;
|
||||||
oit->badLoc = node->getLoc();
|
badLoc = node->getLoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check function calls for arguments modifying the loop index
|
// check function calls for arguments modifying the loop index
|
||||||
bool InductiveAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
|
bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
||||||
{
|
{
|
||||||
TInductiveTraverser* oit = static_cast<TInductiveTraverser*>(it);
|
|
||||||
|
|
||||||
if (node->getOp() == EOpFunctionCall) {
|
if (node->getOp() == EOpFunctionCall) {
|
||||||
// see if an out or inout argument is the loop index
|
// see if an out or inout argument is the loop index
|
||||||
const TIntermSequence& args = node->getSequence();
|
const TIntermSequence& args = node->getSequence();
|
||||||
for (size_t i = 0; i < args.size(); ++i) {
|
for (size_t i = 0; i < args.size(); ++i) {
|
||||||
if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == oit->loopId) {
|
if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == loopId) {
|
||||||
TSymbol* function = oit->symbolTable.find(node->getName());
|
TSymbol* function = symbolTable.find(node->getName());
|
||||||
const TType* type = (*function->getAsFunction())[i].type;
|
const TType* type = (*function->getAsFunction())[i].type;
|
||||||
if (type->getQualifier().storage == EvqOut ||
|
if (type->getQualifier().storage == EvqOut ||
|
||||||
type->getQualifier().storage == EvqInOut) {
|
type->getQualifier().storage == EvqInOut) {
|
||||||
oit->bad = true;
|
bad = true;
|
||||||
oit->badLoc = node->getLoc();
|
badLoc = node->getLoc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,10 +132,6 @@ void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbo
|
|||||||
if (! body)
|
if (! body)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
it.visitAggregate = InductiveAggregate;
|
|
||||||
it.visitBinary = InductiveBinary;
|
|
||||||
it.visitUnary = InductiveUnary;
|
|
||||||
|
|
||||||
body->traverse(&it);
|
body->traverse(&it);
|
||||||
|
|
||||||
if (it.bad)
|
if (it.bad)
|
||||||
@ -151,30 +147,28 @@ void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbo
|
|||||||
class TIndexTraverser : public TIntermTraverser {
|
class TIndexTraverser : public TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { }
|
TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { }
|
||||||
|
virtual void visitSymbol(TIntermSymbol* symbol);
|
||||||
|
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
||||||
const TIdSetType& inductiveLoopIds;
|
const TIdSetType& inductiveLoopIds;
|
||||||
bool bad;
|
bool bad;
|
||||||
TSourceLoc badLoc;
|
TSourceLoc badLoc;
|
||||||
};
|
};
|
||||||
|
|
||||||
// make sure symbols are inductive-loop indexes
|
// make sure symbols are inductive-loop indexes
|
||||||
void IndexSymbol(TIntermSymbol* symbol, TIntermTraverser* it)
|
void TIndexTraverser::visitSymbol(TIntermSymbol* symbol)
|
||||||
{
|
{
|
||||||
TIndexTraverser* oit = static_cast<TIndexTraverser*>(it);
|
if (inductiveLoopIds.find(symbol->getId()) == inductiveLoopIds.end()) {
|
||||||
|
bad = true;
|
||||||
if (oit->inductiveLoopIds.find(symbol->getId()) == oit->inductiveLoopIds.end()) {
|
badLoc = symbol->getLoc();
|
||||||
oit->bad = true;
|
|
||||||
oit->badLoc = symbol->getLoc();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for function calls, assuming they are bad; spec. doesn't really say
|
// check for function calls, assuming they are bad; spec. doesn't really say
|
||||||
bool IndexAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
|
bool TIndexTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
||||||
{
|
{
|
||||||
TIndexTraverser* oit = static_cast<TIndexTraverser*>(it);
|
|
||||||
|
|
||||||
if (node->getOp() == EOpFunctionCall) {
|
if (node->getOp() == EOpFunctionCall) {
|
||||||
oit->bad = true;
|
bad = true;
|
||||||
oit->badLoc = node->getLoc();
|
badLoc = node->getLoc();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -187,9 +181,6 @@ void TParseContext::constantIndexExpressionCheck(TIntermNode* index)
|
|||||||
{
|
{
|
||||||
TIndexTraverser it(inductiveLoopIds);
|
TIndexTraverser it(inductiveLoopIds);
|
||||||
|
|
||||||
it.visitSymbol = IndexSymbol;
|
|
||||||
it.visitAggregate = IndexAggregate;
|
|
||||||
|
|
||||||
index->traverse(&it);
|
index->traverse(&it);
|
||||||
|
|
||||||
if (it.bad)
|
if (it.bad)
|
||||||
|
|||||||
@ -43,9 +43,14 @@ namespace glslang {
|
|||||||
|
|
||||||
class TConstTraverser : public TIntermTraverser {
|
class TConstTraverser : public TIntermTraverser {
|
||||||
public:
|
public:
|
||||||
TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t) : unionArray(cUnion), type(t),
|
TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
|
||||||
|
: unionArray(cUnion), type(t),
|
||||||
constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
|
constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
|
||||||
matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; }
|
matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; }
|
||||||
|
|
||||||
|
virtual void visitConstantUnion(TIntermConstantUnion* node);
|
||||||
|
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
TConstUnionArray unionArray;
|
TConstUnionArray unionArray;
|
||||||
TOperator tOp;
|
TOperator tOp;
|
||||||
@ -59,32 +64,30 @@ public:
|
|||||||
int matrixRows;
|
int matrixRows;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
|
bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
||||||
{
|
{
|
||||||
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
|
||||||
|
|
||||||
if (! node->isConstructor() && node->getOp() != EOpComma) {
|
if (! node->isConstructor() && node->getOp() != EOpComma) {
|
||||||
oit->error = true;
|
error = true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->getSequence().size() == 0) {
|
if (node->getSequence().size() == 0) {
|
||||||
oit->error = true;
|
error = true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
|
bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
|
||||||
if (flag) {
|
if (flag) {
|
||||||
oit->singleConstantParam = true;
|
singleConstantParam = true;
|
||||||
oit->constructorType = node->getOp();
|
constructorType = node->getOp();
|
||||||
oit->size = node->getType().getObjectSize();
|
size = node->getType().getObjectSize();
|
||||||
|
|
||||||
if (node->getType().isMatrix()) {
|
if (node->getType().isMatrix()) {
|
||||||
oit->isMatrix = true;
|
isMatrix = true;
|
||||||
oit->matrixCols = node->getType().getMatrixCols();
|
matrixCols = node->getType().getMatrixCols();
|
||||||
oit->matrixRows = node->getType().getMatrixRows();
|
matrixRows = node->getType().getMatrixRows();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,55 +95,54 @@ bool ParseAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverse
|
|||||||
p != node->getSequence().end(); p++) {
|
p != node->getSequence().end(); p++) {
|
||||||
|
|
||||||
if (node->getOp() == EOpComma)
|
if (node->getOp() == EOpComma)
|
||||||
oit->index = 0;
|
index = 0;
|
||||||
|
|
||||||
(*p)->traverse(oit);
|
(*p)->traverse(this);
|
||||||
}
|
}
|
||||||
if (flag)
|
if (flag)
|
||||||
{
|
{
|
||||||
oit->singleConstantParam = false;
|
singleConstantParam = false;
|
||||||
oit->constructorType = EOpNull;
|
constructorType = EOpNull;
|
||||||
oit->size = 0;
|
size = 0;
|
||||||
oit->isMatrix = false;
|
isMatrix = false;
|
||||||
oit->matrixCols = 0;
|
matrixCols = 0;
|
||||||
oit->matrixRows = 0;
|
matrixRows = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
|
void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
||||||
{
|
{
|
||||||
TConstTraverser* oit = static_cast<TConstTraverser*>(it);
|
TConstUnionArray leftUnionArray(unionArray);
|
||||||
TConstUnionArray leftUnionArray(oit->unionArray);
|
int instanceSize = type.getObjectSize();
|
||||||
int instanceSize = oit->type.getObjectSize();
|
|
||||||
|
|
||||||
if (oit->index >= instanceSize)
|
if (index >= instanceSize)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (! oit->singleConstantParam) {
|
if (! singleConstantParam) {
|
||||||
int size = node->getType().getObjectSize();
|
int rightUnionSize = node->getType().getObjectSize();
|
||||||
|
|
||||||
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < rightUnionSize; i++) {
|
||||||
if (oit->index >= instanceSize)
|
if (index >= instanceSize)
|
||||||
return;
|
return;
|
||||||
leftUnionArray[oit->index] = rightUnionArray[i];
|
leftUnionArray[index] = rightUnionArray[i];
|
||||||
|
|
||||||
oit->index++;
|
index++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int endIndex = oit->index + oit->size;
|
int endIndex = index + size;
|
||||||
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
||||||
if (! oit->isMatrix) {
|
if (! isMatrix) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i = oit->index; i < endIndex; i++) {
|
for (int i = index; i < endIndex; i++) {
|
||||||
if (i >= instanceSize)
|
if (i >= instanceSize)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
leftUnionArray[i] = rightUnionArray[count];
|
leftUnionArray[i] = rightUnionArray[count];
|
||||||
|
|
||||||
(oit->index)++;
|
(index)++;
|
||||||
|
|
||||||
if (node->getType().getObjectSize() > 1)
|
if (node->getType().getObjectSize() > 1)
|
||||||
count++;
|
count++;
|
||||||
@ -148,12 +150,12 @@ void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
|
|||||||
} else {
|
} else {
|
||||||
// constructing a matrix, but from what?
|
// constructing a matrix, but from what?
|
||||||
if (node->isMatrix()) {
|
if (node->isMatrix()) {
|
||||||
// Matrix from a matrix; oit has the outer matrix, node is the argument matrix.
|
// Matrix from a matrix; this has the outer matrix, node is the argument matrix.
|
||||||
// Traverse the outer, potentially bigger matrix, fill in missing pieces with the
|
// Traverse the outer, potentially bigger matrix, fill in missing pieces with the
|
||||||
// identity matrix.
|
// identity matrix.
|
||||||
for (int c = 0; c < oit->matrixCols; ++c) {
|
for (int c = 0; c < matrixCols; ++c) {
|
||||||
for (int r = 0; r < oit->matrixRows; ++r) {
|
for (int r = 0; r < matrixRows; ++r) {
|
||||||
int targetOffset = oit->index + c * oit->matrixRows + r;
|
int targetOffset = index + c * matrixRows + r;
|
||||||
if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
|
if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
|
||||||
int srcOffset = c * node->getType().getMatrixRows() + r;
|
int srcOffset = c * node->getType().getMatrixRows() + r;
|
||||||
leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
|
leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
|
||||||
@ -166,16 +168,16 @@ void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
|
|||||||
} else {
|
} else {
|
||||||
// matrix from vector
|
// matrix from vector
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int index = oit->index;
|
const int startIndex = index;
|
||||||
for (int i = index; i < endIndex; i++) {
|
for (int i = startIndex; i < endIndex; i++) {
|
||||||
if (i >= instanceSize)
|
if (i >= instanceSize)
|
||||||
return;
|
return;
|
||||||
if (i == index || (i - index) % (oit->matrixRows + 1) == 0 )
|
if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
|
||||||
leftUnionArray[i] = rightUnionArray[count];
|
leftUnionArray[i] = rightUnionArray[count];
|
||||||
else
|
else
|
||||||
leftUnionArray[i].setDConst(0.0);
|
leftUnionArray[i].setDConst(0.0);
|
||||||
|
|
||||||
oit->index++;
|
index++;
|
||||||
|
|
||||||
if (node->getType().getObjectSize() > 1)
|
if (node->getType().getObjectSize() > 1)
|
||||||
count++;
|
count++;
|
||||||
@ -192,9 +194,6 @@ bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArra
|
|||||||
|
|
||||||
TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
|
TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
|
||||||
|
|
||||||
it.visitAggregate = ParseAggregate;
|
|
||||||
it.visitConstantUnion = ParseConstantUnion;
|
|
||||||
|
|
||||||
root->traverse(&it);
|
root->traverse(&it);
|
||||||
if (it.error)
|
if (it.error)
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -78,6 +78,11 @@ class TLiveTraverser : public TIntermTraverser {
|
|||||||
public:
|
public:
|
||||||
TLiveTraverser(const TIntermediate& i, TReflection& r) : intermediate(i), reflection(r) { }
|
TLiveTraverser(const TIntermediate& i, TReflection& r) : intermediate(i), reflection(r) { }
|
||||||
|
|
||||||
|
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
||||||
|
virtual bool visitBinary(TVisit, TIntermBinary* node);
|
||||||
|
virtual void visitSymbol(TIntermSymbol* base);
|
||||||
|
virtual bool visitSelection(TVisit, TIntermSelection* node);
|
||||||
|
|
||||||
// Track live funtions as well as uniforms, so that we don't visit dead functions
|
// Track live funtions as well as uniforms, so that we don't visit dead functions
|
||||||
// and only visit each function once.
|
// and only visit each function once.
|
||||||
void addFunctionCall(TIntermAggregate* call)
|
void addFunctionCall(TIntermAggregate* call)
|
||||||
@ -712,34 +717,28 @@ public:
|
|||||||
|
|
||||||
const int TLiveTraverser::baseAlignmentVec4Std140 = 16;
|
const int TLiveTraverser::baseAlignmentVec4Std140 = 16;
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Implement the traversal functions of interest.
|
// Implement the traversal functions of interest.
|
||||||
//
|
//
|
||||||
|
|
||||||
// To catch which function calls are not dead, and hence which functions must be visited.
|
// To catch which function calls are not dead, and hence which functions must be visited.
|
||||||
bool LiveAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
|
bool TLiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
||||||
{
|
{
|
||||||
TLiveTraverser* oit = static_cast<TLiveTraverser*>(it);
|
|
||||||
|
|
||||||
if (node->getOp() == EOpFunctionCall)
|
if (node->getOp() == EOpFunctionCall)
|
||||||
oit->addFunctionCall(node);
|
addFunctionCall(node);
|
||||||
|
|
||||||
return true; // traverse this subtree
|
return true; // traverse this subtree
|
||||||
}
|
}
|
||||||
|
|
||||||
// To catch dereferenced aggregates that must be reflected.
|
// To catch dereferenced aggregates that must be reflected.
|
||||||
// This catches them at the highest level possible in the tree.
|
// This catches them at the highest level possible in the tree.
|
||||||
bool LiveBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
bool TLiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
|
||||||
{
|
{
|
||||||
TLiveTraverser* oit = static_cast<TLiveTraverser*>(it);
|
|
||||||
|
|
||||||
switch (node->getOp()) {
|
switch (node->getOp()) {
|
||||||
case EOpIndexDirect:
|
case EOpIndexDirect:
|
||||||
case EOpIndexIndirect:
|
case EOpIndexIndirect:
|
||||||
case EOpIndexDirectStruct:
|
case EOpIndexDirectStruct:
|
||||||
oit->addDereferencedUniform(node);
|
addDereferencedUniform(node);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -751,34 +750,28 @@ bool LiveBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// To reflect non-dereferenced objects.
|
// To reflect non-dereferenced objects.
|
||||||
void LiveSymbol(TIntermSymbol* base, TIntermTraverser* it)
|
void TLiveTraverser::visitSymbol(TIntermSymbol* base)
|
||||||
{
|
{
|
||||||
TLiveTraverser* oit = static_cast<TLiveTraverser*>(it);
|
|
||||||
|
|
||||||
if (base->getQualifier().storage == EvqUniform)
|
if (base->getQualifier().storage == EvqUniform)
|
||||||
oit->addUniform(*base);
|
addUniform(*base);
|
||||||
}
|
}
|
||||||
|
|
||||||
// To prune semantically dead paths.
|
// To prune semantically dead paths.
|
||||||
bool LiveSelection(bool /* preVisit */, TIntermSelection* node, TIntermTraverser* it)
|
bool TLiveTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node)
|
||||||
{
|
{
|
||||||
TLiveTraverser* oit = static_cast<TLiveTraverser*>(it);
|
|
||||||
|
|
||||||
TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
|
TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
|
||||||
if (constant) {
|
if (constant) {
|
||||||
// cull the path that is dead
|
// cull the path that is dead
|
||||||
if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
|
if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
|
||||||
node->getTrueBlock()->traverse(it);
|
node->getTrueBlock()->traverse(this);
|
||||||
if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
|
if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
|
||||||
node->getFalseBlock()->traverse(it);
|
node->getFalseBlock()->traverse(this);
|
||||||
|
|
||||||
return false; // don't traverse any more, we did it all above
|
return false; // don't traverse any more, we did it all above
|
||||||
} else
|
} else
|
||||||
return true; // traverse the whole subtree
|
return true; // traverse the whole subtree
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end anonymous namespace
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Implement TReflection methods.
|
// Implement TReflection methods.
|
||||||
//
|
//
|
||||||
@ -792,10 +785,6 @@ bool TReflection::addStage(EShLanguage, const TIntermediate& intermediate)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
TLiveTraverser it(intermediate, *this);
|
TLiveTraverser it(intermediate, *this);
|
||||||
it.visitSymbol = LiveSymbol;
|
|
||||||
it.visitSelection = LiveSelection;
|
|
||||||
it.visitBinary = LiveBinary;
|
|
||||||
it.visitAggregate = LiveAggregate;
|
|
||||||
|
|
||||||
// put main() on functions to process
|
// put main() on functions to process
|
||||||
it.pushFunction("main(");
|
it.pushFunction("main(");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user