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
This commit is contained in:
alokp@chromium.org 2010-05-05 18:21:51 +00:00
Родитель 256b751db2
Коммит b3f7fb68c6
2 изменённых файлов: 103 добавлений и 41 удалений

Просмотреть файл

@ -43,7 +43,8 @@ TString getTypeName(const TType& type)
TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink)
: TIntermTraverser(true, true, true),
mObjSink(objSink),
mWriteFullSymbol(false)
mWriteFullSymbol(false),
mScopeSequences(false)
{
}
@ -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)
{
TInfoSinkBase& out = objSink();
@ -106,28 +151,7 @@ void TOutputGLSL::visitSymbol(TIntermSymbol* node)
void TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node)
{
TInfoSinkBase& out = objSink();
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 << ")";
writeConstantUnion(node->getType(), node->getUnionArrayPointer());
}
bool TOutputGLSL::visitBinary(Visit visit, TIntermBinary* node)
@ -331,13 +355,13 @@ bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
{
node->getTrueBlock()->traverse(this);
}
out << "}";
out << ";\n}";
if (node->getFalseBlock())
{
out << " else {\n";
node->getFalseBlock()->traverse(this);
out << "}";
out << ";\n}";
}
decrementDepth();
out << "\n";
@ -347,11 +371,26 @@ bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
{
bool visitChildren = true;
TInfoSinkBase& out = objSink();
switch (node->getOp())
{
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;
case EOpPrototype:
// Function declaration.
@ -373,26 +412,47 @@ bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
mWriteFullSymbol = false;
}
break;
case EOpFunction:
case EOpFunction: {
// Function definition.
if (visit == PreVisit)
TString returnType = getTypeName(node->getType());
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
// 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)
{
TString returnType = getTypeName(node->getType());
TString functionName = TFunction::unmangleName(node->getName());
out << returnType << " " << functionName;
ASSERT(body->getOp() == EOpSequence);
// Sequences are scoped with {} inside function body so that
// variables are declared in the correct scope.
mScopeSequences = true;
body->traverse(this);
mScopeSequences = false;
}
else if (visit == InVisit)
else
{
// Called after traversing function arguments (EOpParameters)
// but before traversing function body (EOpSequence).
out << "{\n";
}
else if (visit == PostVisit)
{
// Called after traversing function body (EOpSequence).
out << "}\n";
// Empty function body.
out << "{}\n";
}
// Fully processed; no need to visit children.
visitChildren = false;
break;
}
case EOpFunctionCall:
// Function call.
if (visit == PreVisit)
@ -503,7 +563,7 @@ bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
default: UNREACHABLE(); break;
}
return true;
return visitChildren;
}
bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)

Просмотреть файл

@ -18,6 +18,7 @@ public:
protected:
TInfoSinkBase& objSink() { return mObjSink; }
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 visitConstantUnion(TIntermConstantUnion* node);
@ -31,6 +32,7 @@ protected:
private:
TInfoSinkBase& mObjSink;
bool mWriteFullSymbol;
bool mScopeSequences;
// Structs are declared as the tree is traversed. This set contains all
// the structs already declared. It is maintained so that a struct is