1a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
2a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Use of this source code is governed by a BSD-style license that can be
4a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// found in the LICENSE file.
5a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
6a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
7a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block#include "compiler/OutputGLSL.h"
8a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block#include "compiler/debug.h"
9a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
10a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blocknamespace
11a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
12a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve BlockTString getTypeName(const TType& type)
13a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
14a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase out;
15a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (type.isMatrix())
16a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
17a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "mat";
18a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << type.getNominalSize();
19a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
20a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else if (type.isVector())
21a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
22a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        switch (type.getBasicType())
23a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        {
24a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            case EbtFloat: out << "vec"; break;
25a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            case EbtInt: out << "ivec"; break;
26a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            case EbtBool: out << "bvec"; break;
27a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            default: UNREACHABLE(); break;
28a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
29a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << type.getNominalSize();
30a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
31a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else
32a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
33a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (type.getBasicType() == EbtStruct)
34a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << type.getTypeName();
35a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        else
36a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << type.getBasicString();
37a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
38a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return TString(out.c_str());
39a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
40a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
41a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve BlockTString arrayBrackets(const TType& type)
42a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
43a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    ASSERT(type.isArray());
44a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase out;
45a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    out << "[" << type.getArraySize() << "]";
46a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return TString(out.c_str());
47a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
48a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
49a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool isSingleStatement(TIntermNode* node) {
50a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (const TIntermAggregate* aggregate = node->getAsAggregate())
51a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
52a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return (aggregate->getOp() != EOpFunction) &&
53a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block               (aggregate->getOp() != EOpSequence);
54a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
55a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else if (const TIntermSelection* selection = node->getAsSelectionNode())
56a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
57a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // Ternary operators are usually part of an assignment operator.
58a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // This handles those rare cases in which they are all by themselves.
59a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return selection->usesTernaryOperator();
60a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
61a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else if (node->getAsLoopNode())
62a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
63a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return false;
64a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
65a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
66a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
67a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}  // namespace
68a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
69a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve BlockTOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink)
70a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    : TIntermTraverser(true, true, true),
71a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      mObjSink(objSink),
72a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block      mDeclaringVariables(false)
73a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
74a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
75a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
76a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid TOutputGLSL::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
77a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
78a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase& out = objSink();
79a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (visit == PreVisit && preStr)
80a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
81a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << preStr;
82a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
83a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else if (visit == InVisit && inStr)
84a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
85a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << inStr;
86a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
87a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else if (visit == PostVisit && postStr)
88a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
89a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << postStr;
90a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
91a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
92a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
93a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid TOutputGLSL::writeVariableType(const TType& type)
94a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
95a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase& out = objSink();
96a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TQualifier qualifier = type.getQualifier();
97a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // TODO(alokp): Validate qualifier for variable declarations.
98a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
99a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << type.getQualifierString() << " ";
100a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
101a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // Declare the struct if we have not done so already.
102a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if ((type.getBasicType() == EbtStruct) &&
103a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        (mDeclaredStructs.find(type.getTypeName()) == mDeclaredStructs.end()))
104a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
105a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "struct " << type.getTypeName() << "{\n";
106a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        const TTypeList* structure = type.getStruct();
107a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(structure != NULL);
108a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        for (size_t i = 0; i < structure->size(); ++i)
109a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        {
110a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            const TType* fieldType = (*structure)[i].type;
111a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ASSERT(fieldType != NULL);
112a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << getTypeName(*fieldType) << " " << fieldType->getFieldName();
113a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (fieldType->isArray())
114a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << arrayBrackets(*fieldType);
115a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << ";\n";
116a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
117a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "}";
118a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        mDeclaredStructs.insert(type.getTypeName());
119a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
120a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else
121a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
122a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << getTypeName(type);
123a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
124a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
125a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
126a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid TOutputGLSL::writeFunctionParameters(const TIntermSequence& args)
127a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
128a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase& out = objSink();
129a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    for (TIntermSequence::const_iterator iter = args.begin();
130a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block         iter != args.end(); ++iter)
131a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
132a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        const TIntermSymbol* arg = (*iter)->getAsSymbolNode();
133a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(arg != NULL);
134a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
135a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        const TType& type = arg->getType();
136a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        TQualifier qualifier = type.getQualifier();
137a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // TODO(alokp): Validate qualifier for function arguments.
138a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
139a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << type.getQualifierString() << " ";
140a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
141a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << getTypeName(type);
142a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
143a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        const TString& name = arg->getSymbol();
144a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (!name.empty())
145a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << " " << name;
146a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (type.isArray())
147a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << arrayBrackets(type);
148a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
149a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // Put a comma if this is not the last argument.
1505abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick        if (iter != args.end() - 1)
151a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << ", ";
152a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
153a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
154a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
155a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockconst ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type,
156a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                                                     const ConstantUnion* pConstUnion)
157a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
158a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase& out = objSink();
159a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
160a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (type.getBasicType() == EbtStruct)
161a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
162a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << type.getTypeName() << "(";
163a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        const TTypeList* structure = type.getStruct();
164a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ASSERT(structure != NULL);
165a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        for (size_t i = 0; i < structure->size(); ++i)
166a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        {
167a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            const TType* fieldType = (*structure)[i].type;
168a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ASSERT(fieldType != NULL);
169a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
170a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (i != structure->size() - 1) out << ", ";
171a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
172a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << ")";
173a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
174a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else
175a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
176a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        int size = type.getObjectSize();
177a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        bool writeType = size > 1;
178a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (writeType) out << getTypeName(type) << "(";
179a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        for (int i = 0; i < size; ++i, ++pConstUnion)
180a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        {
181a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            switch (pConstUnion->getType())
182a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
183a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case EbtFloat: out << pConstUnion->getFConst(); break;
184a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case EbtInt: out << pConstUnion->getIConst(); break;
185a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case EbtBool: out << pConstUnion->getBConst(); break;
186a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                default: UNREACHABLE();
187a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
188a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (i != size - 1) out << ", ";
189a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
190a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (writeType) out << ")";
191a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
192a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return pConstUnion;
193a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
194a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
195a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid TOutputGLSL::visitSymbol(TIntermSymbol* node)
196a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
197a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase& out = objSink();
198a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    out << node->getSymbol();
199a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
200a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (mDeclaringVariables && node->getType().isArray())
201a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << arrayBrackets(node->getType());
202a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
203a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
204a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node)
205a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
206a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    writeConstantUnion(node->getType(), node->getUnionArrayPointer());
207a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
208a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
209a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputGLSL::visitBinary(Visit visit, TIntermBinary* node)
210a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
211a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    bool visitChildren = true;
212a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase& out = objSink();
213a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (node->getOp())
214a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
215a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpInitialize:
216a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (visit == InVisit)
217a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
218a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << " = ";
219a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                // RHS of initialize is not being declared.
220a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                mDeclaringVariables = false;
221a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
222a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
223a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
224a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
225a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
226a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
227a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // Notice the fall-through.
228a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMulAssign:
229a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpVectorTimesMatrixAssign:
230a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpVectorTimesScalarAssign:
231a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMatrixTimesScalarAssign:
232a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMatrixTimesMatrixAssign:
233a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            writeTriplet(visit, "(", " *= ", ")");
234a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
235a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
236a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpIndexDirect:
237a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpIndexIndirect:
238a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            writeTriplet(visit, NULL, "[", "]");
239a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
240a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpIndexDirectStruct:
241a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (visit == InVisit)
242a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
243a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << ".";
244a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                // TODO(alokp): ASSERT
245a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << node->getType().getFieldName();
246a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                visitChildren = false;
247a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
248a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
249a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpVectorSwizzle:
250a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (visit == InVisit)
251a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
252a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << ".";
253a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
254a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                TIntermSequence& sequence = rightChild->getSequence();
255a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
256a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                {
257a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                    TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
258a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                    ASSERT(element->getBasicType() == EbtInt);
259a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                    ASSERT(element->getNominalSize() == 1);
260a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                    const ConstantUnion& data = element->getUnionArrayPointer()[0];
261a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                    ASSERT(data.getType() == EbtInt);
262a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                    switch (data.getIConst())
263a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                    {
264a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                        case 0: out << "x"; break;
265a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                        case 1: out << "y"; break;
266a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                        case 2: out << "z"; break;
267a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                        case 3: out << "w"; break;
268a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                        default: UNREACHABLE(); break;
269a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                    }
270a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                }
271a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                visitChildren = false;
272a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
273a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
274a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
275a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
276a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
277a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
278a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
279a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMod: UNIMPLEMENTED(); break;
280a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
281a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
282a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
283a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
284a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
285a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
286a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
287a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // Notice the fall-through.
288a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpVectorTimesScalar:
289a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpVectorTimesMatrix:
290a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMatrixTimesVector:
291a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMatrixTimesScalar:
292a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMatrixTimesMatrix:
293a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            writeTriplet(visit, "(", " * ", ")");
294a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
295a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
296a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
297a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
298a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
299a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        default: UNREACHABLE(); break;
300a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
301a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
302a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return visitChildren;
303a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
304a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
305a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputGLSL::visitUnary(Visit visit, TIntermUnary* node)
306a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
307a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (node->getOp())
308a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
309a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpNegative: writeTriplet(visit, "(-", NULL, ")"); break;
310a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpVectorLogicalNot: writeTriplet(visit, "not(", NULL, ")"); break;
311a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLogicalNot: writeTriplet(visit, "(!", NULL, ")"); break;
312a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
313a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpPostIncrement: writeTriplet(visit, "(", NULL, "++)"); break;
314a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpPostDecrement: writeTriplet(visit, "(", NULL, "--)"); break;
315a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpPreIncrement: writeTriplet(visit, "(++", NULL, ")"); break;
316a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpPreDecrement: writeTriplet(visit, "(--", NULL, ")"); break;
317a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
318a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConvIntToBool:
319a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConvFloatToBool:
320a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            switch (node->getOperand()->getType().getNominalSize())
321a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
322a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 1: writeTriplet(visit, "bool(", NULL, ")");  break;
323a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 2: writeTriplet(visit, "bvec2(", NULL, ")"); break;
324a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 3: writeTriplet(visit, "bvec3(", NULL, ")"); break;
325a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 4: writeTriplet(visit, "bvec4(", NULL, ")"); break;
326a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                default: UNREACHABLE();
327a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
328a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
329a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConvBoolToFloat:
330a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConvIntToFloat:
331a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            switch (node->getOperand()->getType().getNominalSize())
332a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
333a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 1: writeTriplet(visit, "float(", NULL, ")");  break;
334a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 2: writeTriplet(visit, "vec2(", NULL, ")"); break;
335a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 3: writeTriplet(visit, "vec3(", NULL, ")"); break;
336a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 4: writeTriplet(visit, "vec4(", NULL, ")"); break;
337a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                default: UNREACHABLE();
338a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
339a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
340a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConvFloatToInt:
341a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConvBoolToInt:
342a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            switch (node->getOperand()->getType().getNominalSize())
343a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
344a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 1: writeTriplet(visit, "int(", NULL, ")");  break;
345a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 2: writeTriplet(visit, "ivec2(", NULL, ")"); break;
346a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 3: writeTriplet(visit, "ivec3(", NULL, ")"); break;
347a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                case 4: writeTriplet(visit, "ivec4(", NULL, ")"); break;
348a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                default: UNREACHABLE();
349a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
350a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
351a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
352a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpRadians: writeTriplet(visit, "radians(", NULL, ")"); break;
353a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpDegrees: writeTriplet(visit, "degrees(", NULL, ")"); break;
354a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpSin: writeTriplet(visit, "sin(", NULL, ")"); break;
355a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpCos: writeTriplet(visit, "cos(", NULL, ")"); break;
356a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpTan: writeTriplet(visit, "tan(", NULL, ")"); break;
357a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAsin: writeTriplet(visit, "asin(", NULL, ")"); break;
358a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAcos: writeTriplet(visit, "acos(", NULL, ")"); break;
359a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAtan: writeTriplet(visit, "atan(", NULL, ")"); break;
360a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
361a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpExp: writeTriplet(visit, "exp(", NULL, ")"); break;
362a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLog: writeTriplet(visit, "log(", NULL, ")"); break;
363a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpExp2: writeTriplet(visit, "exp2(", NULL, ")"); break;
364a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLog2: writeTriplet(visit, "log2(", NULL, ")"); break;
365a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpSqrt: writeTriplet(visit, "sqrt(", NULL, ")"); break;
366a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpInverseSqrt: writeTriplet(visit, "inversesqrt(", NULL, ")"); break;
367a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
368a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAbs: writeTriplet(visit, "abs(", NULL, ")"); break;
369a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpSign: writeTriplet(visit, "sign(", NULL, ")"); break;
370a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpFloor: writeTriplet(visit, "floor(", NULL, ")"); break;
371a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpCeil: writeTriplet(visit, "ceil(", NULL, ")"); break;
372a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpFract: writeTriplet(visit, "fract(", NULL, ")"); break;
373a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
374a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLength: writeTriplet(visit, "length(", NULL, ")"); break;
375a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpNormalize: writeTriplet(visit, "normalize(", NULL, ")"); break;
376a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
377ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpDFdx: writeTriplet(visit, "dFdx(", NULL, ")"); break;
378ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpDFdy: writeTriplet(visit, "dFdy(", NULL, ")"); break;
379ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpFwidth: writeTriplet(visit, "fwidth(", NULL, ")"); break;
380ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
381a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAny: writeTriplet(visit, "any(", NULL, ")"); break;
382a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAll: writeTriplet(visit, "all(", NULL, ")"); break;
383a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
384a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        default: UNREACHABLE(); break;
385a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
386a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
387a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
388a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
389a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
390a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
391a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
392a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase& out = objSink();
393a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
394a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (node->usesTernaryOperator())
395a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
396a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // Notice two brackets at the beginning and end. The outer ones
397a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // encapsulate the whole ternary expression. This preserves the
398a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // order of precedence when ternary expressions are used in a
399a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
400a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "((";
401a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        node->getCondition()->traverse(this);
402a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << ") ? (";
403a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        node->getTrueBlock()->traverse(this);
404a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << ") : (";
405a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        node->getFalseBlock()->traverse(this);
406a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "))";
407a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
408a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else
409a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
410a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "if (";
411a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        node->getCondition()->traverse(this);
412a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << ")\n";
413a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
414a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        incrementDepth();
415a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        visitCodeBlock(node->getTrueBlock());
416a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
417a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (node->getFalseBlock())
418a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        {
419a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << "else\n";
420a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            visitCodeBlock(node->getFalseBlock());
421a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
422a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        decrementDepth();
423a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
424a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return false;
425a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
426a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
427a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
428a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
429a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    bool visitChildren = true;
430a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase& out = objSink();
431a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (node->getOp())
432a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
433a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpSequence: {
434a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Scope the sequences except when at the global scope.
435a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (depth > 0) out << "{\n";
436a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
437a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            incrementDepth();
438a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            const TIntermSequence& sequence = node->getSequence();
439a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            for (TIntermSequence::const_iterator iter = sequence.begin();
440a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                 iter != sequence.end(); ++iter)
441a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
442a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                TIntermNode* node = *iter;
443a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                ASSERT(node != NULL);
444a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                node->traverse(this);
445a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
446a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                if (isSingleStatement(node))
447a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                    out << ";\n";
448a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
449a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            decrementDepth();
450a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
451a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Scope the sequences except when at the global scope.
452a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (depth > 0) out << "}\n";
453a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            visitChildren = false;
454a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
455a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
456a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpPrototype: {
457a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Function declaration.
458a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ASSERT(visit == PreVisit);
459a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            TString returnType = getTypeName(node->getType());
460a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << returnType << " " << node->getName();
461a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
462a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << "(";
463a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            writeFunctionParameters(node->getSequence());
464a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << ")";
465a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
466a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            visitChildren = false;
467a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
468a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
469a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpFunction: {
470a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Function definition.
471a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ASSERT(visit == PreVisit);
472a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            TString returnType = getTypeName(node->getType());
473a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            TString functionName = TFunction::unmangleName(node->getName());
474a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << returnType << " " << functionName;
475a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
476a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            incrementDepth();
477a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Function definition node contains one or two children nodes
478a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // representing function parameters and function body. The latter
479a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // is not present in case of empty function bodies.
480a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            const TIntermSequence& sequence = node->getSequence();
481a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ASSERT((sequence.size() == 1) || (sequence.size() == 2));
482a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            TIntermSequence::const_iterator seqIter = sequence.begin();
483a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
484a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Traverse function parameters.
485a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            TIntermAggregate* params = (*seqIter)->getAsAggregate();
486a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ASSERT(params != NULL);
487a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ASSERT(params->getOp() == EOpParameters);
488a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            params->traverse(this);
489a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
490a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Traverse function body.
491a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            TIntermAggregate* body = ++seqIter != sequence.end() ?
492a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                (*seqIter)->getAsAggregate() : NULL;
493a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            visitCodeBlock(body);
494a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            decrementDepth();
495a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
496a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Fully processed; no need to visit children.
497a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            visitChildren = false;
498a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
499a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
500a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpFunctionCall:
501a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Function call.
502a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (visit == PreVisit)
503a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
504a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                TString functionName = TFunction::unmangleName(node->getName());
505a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << functionName << "(";
506a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
507a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            else if (visit == InVisit)
508a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
509a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << ", ";
510a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
511a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            else
512a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
513a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << ")";
514a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
515a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
516a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpParameters: {
517a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Function parameters.
518a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            ASSERT(visit == PreVisit);
519a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << "(";
520a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            writeFunctionParameters(node->getSequence());
521a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << ")";
522a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            visitChildren = false;
523a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
524a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
525a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpDeclaration: {
526a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            // Variable declaration.
527a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (visit == PreVisit)
528a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
529a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                const TIntermSequence& sequence = node->getSequence();
530a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                const TIntermTyped* variable = sequence.front()->getAsTyped();
531a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                writeVariableType(variable->getType());
532a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << " ";
533a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                mDeclaringVariables = true;
534a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
535a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            else if (visit == InVisit)
536a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
537a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << ", ";
538a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                mDeclaringVariables = true;
539a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
540a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            else
541a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
542a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                mDeclaringVariables = false;
543a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
544a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
545a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
546a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
547a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
548a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
549a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
550a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
551a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
552a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
553a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
554a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
555a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
556a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
557a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
558a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
559a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
560a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
561a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpConstructStruct:
562a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            if (visit == PreVisit)
563a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
564a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                const TType& type = node->getType();
565a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                ASSERT(type.getBasicType() == EbtStruct);
566a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << type.getTypeName() << "(";
567a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
568a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            else if (visit == InVisit)
569a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
570a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << ", ";
571a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
572a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            else
573a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            {
574a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                out << ")";
575a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            }
576a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            break;
577a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
578a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLessThan: writeTriplet(visit, "lessThan(", ", ", ")"); break;
579a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpGreaterThan: writeTriplet(visit, "greaterThan(", ", ", ")"); break;
580a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpLessThanEqual: writeTriplet(visit, "lessThanEqual(", ", ", ")"); break;
581a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpGreaterThanEqual: writeTriplet(visit, "greaterThanEqual(", ", ", ")"); break;
582a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpVectorEqual: writeTriplet(visit, "equal(", ", ", ")"); break;
583a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpVectorNotEqual: writeTriplet(visit, "notEqual(", ", ", ")"); break;
584a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
585a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
586a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMod: writeTriplet(visit, "mod(", ", ", ")"); break;
587a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpPow: writeTriplet(visit, "pow(", ", ", ")"); break;
588a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpAtan: writeTriplet(visit, "atan(", ", ", ")"); break;
589a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMin: writeTriplet(visit, "min(", ", ", ")"); break;
590a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMax: writeTriplet(visit, "max(", ", ", ")"); break;
591a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpClamp: writeTriplet(visit, "clamp(", ", ", ")"); break;
592a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMix: writeTriplet(visit, "mix(", ", ", ")"); break;
593a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpStep: writeTriplet(visit, "step(", ", ", ")"); break;
594a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpSmoothStep: writeTriplet(visit, "smoothstep(", ", ", ")"); break;
595a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
596a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpDistance: writeTriplet(visit, "distance(", ", ", ")"); break;
597a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpDot: writeTriplet(visit, "dot(", ", ", ")"); break;
598a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpCross: writeTriplet(visit, "cross(", ", ", ")"); break;
599a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpFaceForward: writeTriplet(visit, "faceforward(", ", ", ")"); break;
600a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpReflect: writeTriplet(visit, "reflect(", ", ", ")"); break;
601a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpRefract: writeTriplet(visit, "refract(", ", ", ")"); break;
602a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpMul: writeTriplet(visit, "matrixCompMult(", ", ", ")"); break;
603a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
604a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        default: UNREACHABLE(); break;
605a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
606a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return visitChildren;
607a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
608a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
609a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
610a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
611a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase& out = objSink();
612a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
613a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    incrementDepth();
614a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // Loop header.
615ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TLoopType loopType = node->getType();
616ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (loopType == ELoopFor)  // for loop
617a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
618a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "for (";
619a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (node->getInit())
620a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            node->getInit()->traverse(this);
621a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "; ";
622a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
623ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        if (node->getCondition())
624ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            node->getCondition()->traverse(this);
625a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "; ";
626a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
627ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        if (node->getExpression())
628ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            node->getExpression()->traverse(this);
629ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << ")\n";
630ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    }
631ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    else if (loopType == ELoopWhile)  // while loop
632ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    {
633ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "while (";
634ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        ASSERT(node->getCondition() != NULL);
635ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        node->getCondition()->traverse(this);
636a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << ")\n";
637a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
638a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else  // do-while loop
639a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
640ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        ASSERT(loopType == ELoopDoWhile);
641a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "do\n";
642a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
643a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
644a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // Loop body.
645a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    visitCodeBlock(node->getBody());
646a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
647a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // Loop footer.
648ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (loopType == ELoopDoWhile)  // do-while loop
649a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
650a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "while (";
651ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        ASSERT(node->getCondition() != NULL);
652ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        node->getCondition()->traverse(this);
653a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << ");\n";
654a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
655a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    decrementDepth();
656a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
657a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // No need to visit children. They have been already processed in
658a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    // this function.
659a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return false;
660a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
661a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
662a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputGLSL::visitBranch(Visit visit, TIntermBranch* node)
663a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
664a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (node->getFlowOp())
665a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
666a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
667a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
668a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
669a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
670a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        default: UNREACHABLE(); break;
671a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
672a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
673a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
674a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
675a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
676a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid TOutputGLSL::visitCodeBlock(TIntermNode* node) {
677a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TInfoSinkBase &out = objSink();
678a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (node != NULL)
679a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
680a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        node->traverse(this);
681a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // Single statements not part of a sequence need to be terminated
682a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        // with semi-colon.
683a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        if (isSingleStatement(node))
684a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            out << ";\n";
685a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
686a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else
687a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    {
688a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        out << "{\n}\n";  // Empty code block.
689a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
690a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
691