Commit b3f7fb68 by alokp@chromium.org

Recursively write ConstantUnion to correctly construct structs.

Review URL: http://codereview.appspot.com/1108041 git-svn-id: https://angleproject.googlecode.com/svn/trunk@229 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 256b751d
...@@ -43,7 +43,8 @@ TString getTypeName(const TType& type) ...@@ -43,7 +43,8 @@ TString getTypeName(const TType& type)
TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink) TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink)
: TIntermTraverser(true, true, true), : TIntermTraverser(true, true, true),
mObjSink(objSink), mObjSink(objSink),
mWriteFullSymbol(false) mWriteFullSymbol(false),
mScopeSequences(false)
{ {
} }
...@@ -64,6 +65,50 @@ void TOutputGLSL::writeTriplet(Visit visit, const char* preStr, const char* inSt ...@@ -64,6 +65,50 @@ void TOutputGLSL::writeTriplet(Visit visit, const char* preStr, const char* inSt
} }
} }
const ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion)
{
TInfoSinkBase& out = objSink();
if (type.getBasicType() == EbtStruct)
{
out << type.getTypeName() << "(";
const TTypeList* structure = type.getStruct();
ASSERT(structure != NULL);
for (size_t i = 0; i < structure->size(); ++i)
{
const TType* fieldType = (*structure)[i].type;
ASSERT(fieldType != NULL);
pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
if (i != structure->size() - 1) out << ", ";
}
out << ")";
}
else
{
int size = type.getObjectSize();
bool writeType = size > 1;
if (writeType) out << getTypeName(type) << "(";
for (int i = 0; i < size; ++i, ++pConstUnion)
{
switch (pConstUnion->getType())
{
case EbtFloat: out << pConstUnion->getFConst(); break;
case EbtInt: out << pConstUnion->getIConst(); break;
case EbtBool:
if (pConstUnion->getBConst())
out << "true";
else
out << "false";
break;
default: UNREACHABLE();
}
if (i != size - 1) out << ", ";
}
if (writeType) out << ")";
}
return pConstUnion;
}
void TOutputGLSL::visitSymbol(TIntermSymbol* node) void TOutputGLSL::visitSymbol(TIntermSymbol* node)
{ {
TInfoSinkBase& out = objSink(); TInfoSinkBase& out = objSink();
...@@ -106,28 +151,7 @@ void TOutputGLSL::visitSymbol(TIntermSymbol* node) ...@@ -106,28 +151,7 @@ void TOutputGLSL::visitSymbol(TIntermSymbol* node)
void TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node) void TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node)
{ {
TInfoSinkBase& out = objSink(); writeConstantUnion(node->getType(), node->getUnionArrayPointer());
const TType& type = node->getType();
int size = type.getObjectSize();
bool writeType = (size > 1) || (type.getBasicType() == EbtStruct);
if (writeType)
out << getTypeName(type) << "(";
for (int i = 0; i < size; ++i)
{
const ConstantUnion& data = node->getUnionArrayPointer()[i];
switch (data.getType())
{
case EbtFloat: out << data.getFConst(); break;
case EbtInt: out << data.getIConst(); break;
case EbtBool: out << data.getBConst(); break;
default: UNREACHABLE(); break;
}
if (i != size - 1)
out << ", ";
}
if (writeType)
out << ")";
} }
bool TOutputGLSL::visitBinary(Visit visit, TIntermBinary* node) bool TOutputGLSL::visitBinary(Visit visit, TIntermBinary* node)
...@@ -331,13 +355,13 @@ bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node) ...@@ -331,13 +355,13 @@ bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
{ {
node->getTrueBlock()->traverse(this); node->getTrueBlock()->traverse(this);
} }
out << "}"; out << ";\n}";
if (node->getFalseBlock()) if (node->getFalseBlock())
{ {
out << " else {\n"; out << " else {\n";
node->getFalseBlock()->traverse(this); node->getFalseBlock()->traverse(this);
out << "}"; out << ";\n}";
} }
decrementDepth(); decrementDepth();
out << "\n"; out << "\n";
...@@ -347,11 +371,26 @@ bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node) ...@@ -347,11 +371,26 @@ bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node) bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
{ {
bool visitChildren = true;
TInfoSinkBase& out = objSink(); TInfoSinkBase& out = objSink();
switch (node->getOp()) switch (node->getOp())
{ {
case EOpSequence: case EOpSequence:
writeTriplet(visit, NULL, ";\n", ";\n"); if (visit == PreVisit)
{
if (mScopeSequences)
out << "{\n";
}
else if (visit == InVisit)
{
out << ";\n";
}
else if (visit == PostVisit)
{
out << ";\n";
if (mScopeSequences)
out << "}\n";
}
break; break;
case EOpPrototype: case EOpPrototype:
// Function declaration. // Function declaration.
...@@ -373,26 +412,47 @@ bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -373,26 +412,47 @@ bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
mWriteFullSymbol = false; mWriteFullSymbol = false;
} }
break; break;
case EOpFunction: case EOpFunction: {
// Function definition. // Function definition.
if (visit == PreVisit) TString returnType = getTypeName(node->getType());
{ TString functionName = TFunction::unmangleName(node->getName());
TString returnType = getTypeName(node->getType()); out << returnType << " " << functionName;
TString functionName = TFunction::unmangleName(node->getName());
out << returnType << " " << functionName; // Function definition node contains one or two children nodes
} // representing function parameters and function body. The latter
else if (visit == InVisit) // is not present in case of empty function bodies.
const TIntermSequence& sequence = node->getSequence();
ASSERT((sequence.size() == 1) || (sequence.size() == 2));
TIntermSequence::const_iterator seqIter = sequence.begin();
// Traverse function parameters.
TIntermAggregate* params = (*seqIter)->getAsAggregate();
ASSERT(params != NULL);
ASSERT(params->getOp() == EOpParameters);
params->traverse(this);
// Traverse function body.
TIntermAggregate* body = ++seqIter != sequence.end() ?
(*seqIter)->getAsAggregate() : NULL;
if (body != NULL)
{ {
// Called after traversing function arguments (EOpParameters) ASSERT(body->getOp() == EOpSequence);
// but before traversing function body (EOpSequence). // Sequences are scoped with {} inside function body so that
out << "{\n"; // variables are declared in the correct scope.
mScopeSequences = true;
body->traverse(this);
mScopeSequences = false;
} }
else if (visit == PostVisit) else
{ {
// Called after traversing function body (EOpSequence). // Empty function body.
out << "}\n"; out << "{}\n";
} }
// Fully processed; no need to visit children.
visitChildren = false;
break; break;
}
case EOpFunctionCall: case EOpFunctionCall:
// Function call. // Function call.
if (visit == PreVisit) if (visit == PreVisit)
...@@ -503,7 +563,7 @@ bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node) ...@@ -503,7 +563,7 @@ bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
default: UNREACHABLE(); break; default: UNREACHABLE(); break;
} }
return true; return visitChildren;
} }
bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node) bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
......
...@@ -18,6 +18,7 @@ public: ...@@ -18,6 +18,7 @@ public:
protected: protected:
TInfoSinkBase& objSink() { return mObjSink; } TInfoSinkBase& objSink() { return mObjSink; }
void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr); void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr);
const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion);
virtual void visitSymbol(TIntermSymbol* node); virtual void visitSymbol(TIntermSymbol* node);
virtual void visitConstantUnion(TIntermConstantUnion* node); virtual void visitConstantUnion(TIntermConstantUnion* node);
...@@ -31,6 +32,7 @@ protected: ...@@ -31,6 +32,7 @@ protected:
private: private:
TInfoSinkBase& mObjSink; TInfoSinkBase& mObjSink;
bool mWriteFullSymbol; bool mWriteFullSymbol;
bool mScopeSequences;
// Structs are declared as the tree is traversed. This set contains all // Structs are declared as the tree is traversed. This set contains all
// the structs already declared. It is maintained so that a struct is // the structs already declared. It is maintained so that a struct is
......
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