summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp
blob: 115c561c775f1561677f199c6ec19c38aa7d87e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//
// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "compiler/translator/InitializeVariables.h"
#include "compiler/translator/compilerdebug.h"

namespace
{

TIntermConstantUnion* constructFloatConstUnionNode(const TType& type)
{
    TType myType = type;
    unsigned char size = myType.getNominalSize();
    if (myType.isMatrix())
        size *= size;
    ConstantUnion *u = new ConstantUnion[size];
    for (int ii = 0; ii < size; ++ii)
        u[ii].setFConst(0.0f);

    myType.clearArrayness();
    myType.setQualifier(EvqConst);
    TIntermConstantUnion *node = new TIntermConstantUnion(u, myType);
    return node;
}

TIntermConstantUnion* constructIndexNode(int index)
{
    ConstantUnion *u = new ConstantUnion[1];
    u[0].setIConst(index);

    TType type(EbtInt, EbpUndefined, EvqConst, 1);
    TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
    return node;
}

}  // namespace anonymous

bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node)
{
    bool visitChildren = !mCodeInserted;
    switch (node->getOp())
    {
      case EOpSequence:
        break;
      case EOpFunction:
      {
        // Function definition.
        ASSERT(visit == PreVisit);
        if (node->getName() == "main(")
        {
            TIntermSequence &sequence = node->getSequence();
            ASSERT((sequence.size() == 1) || (sequence.size() == 2));
            TIntermAggregate *body = NULL;
            if (sequence.size() == 1)
            {
                body = new TIntermAggregate(EOpSequence);
                sequence.push_back(body);
            }
            else
            {
                body = sequence[1]->getAsAggregate();
            }
            ASSERT(body);
            insertInitCode(body->getSequence());
            mCodeInserted = true;
        }
        break;
      }
      default:
        visitChildren = false;
        break;
    }
    return visitChildren;
}

void InitializeVariables::insertInitCode(TIntermSequence& sequence)
{
    for (size_t ii = 0; ii < mVariables.size(); ++ii)
    {
        const InitVariableInfo& varInfo = mVariables[ii];

        if (varInfo.type.isArray())
        {
            for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index)
            {
                TIntermBinary *assign = new TIntermBinary(EOpAssign);
                sequence.insert(sequence.begin(), assign);

                TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
                TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
                indexDirect->setLeft(symbol);
                TIntermConstantUnion *indexNode = constructIndexNode(index);
                indexDirect->setRight(indexNode);

                assign->setLeft(indexDirect);

                TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
                assign->setRight(zeroConst);
            }
        }
        else
        {
            TIntermBinary *assign = new TIntermBinary(EOpAssign);
            sequence.insert(sequence.begin(), assign);
            TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
            assign->setLeft(symbol);
            TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
            assign->setRight(zeroConst);
        }

    }
}