From b3f7fb68c650f8109a3dd8cb26452a141a7afde0 Mon Sep 17 00:00:00 2001 From: "alokp@chromium.org" Date: Wed, 5 May 2010 18:21:51 +0000 Subject: [PATCH] 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 --- src/compiler/OutputGLSL.cpp | 142 +++++++++++++++++++++++++----------- src/compiler/OutputGLSL.h | 2 + 2 files changed, 103 insertions(+), 41 deletions(-) diff --git a/src/compiler/OutputGLSL.cpp b/src/compiler/OutputGLSL.cpp index 3b639e9ca..219909eb7 100644 --- a/src/compiler/OutputGLSL.cpp +++ b/src/compiler/OutputGLSL.cpp @@ -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) diff --git a/src/compiler/OutputGLSL.h b/src/compiler/OutputGLSL.h index a25ea452c..8c2c33a30 100644 --- a/src/compiler/OutputGLSL.h +++ b/src/compiler/OutputGLSL.h @@ -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