blob: 482260ae2b455924801f761a97c0b7c053f3d84c [file] [log] [blame]
Zhenyao Mo4a667fe2014-02-11 12:35:01 -08001//
2// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7#include "compiler/translator/InitializeVariables.h"
Olli Etuahod57e0db2015-04-24 15:05:08 +03008
Zhenyao Mo72111912016-07-20 17:45:56 -07009#include "angle_gl.h"
Olli Etuahod57e0db2015-04-24 15:05:08 +030010#include "common/debug.h"
Zhenyao Mo72111912016-07-20 17:45:56 -070011#include "compiler/translator/IntermNode.h"
12#include "compiler/translator/util.h"
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080013
14namespace
15{
16
Zhenyao Mo72111912016-07-20 17:45:56 -070017TIntermConstantUnion *constructConstUnionNode(const TType &type)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080018{
19 TType myType = type;
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080020 myType.clearArrayness();
21 myType.setQualifier(EvqConst);
Zhenyao Mo72111912016-07-20 17:45:56 -070022 size_t size = myType.getObjectSize();
23 TConstantUnion *u = new TConstantUnion[size];
24 for (size_t ii = 0; ii < size; ++ii)
25 {
26 switch (type.getBasicType())
27 {
28 case EbtFloat:
29 u[ii].setFConst(0.0f);
30 break;
31 case EbtInt:
32 u[ii].setIConst(0);
33 break;
34 case EbtUInt:
35 u[ii].setUConst(0u);
36 break;
37 default:
38 UNREACHABLE();
39 return nullptr;
40 }
41 }
42
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080043 TIntermConstantUnion *node = new TIntermConstantUnion(u, myType);
44 return node;
45}
46
Zhenyao Moe40d1e92014-07-16 17:40:36 -070047TIntermConstantUnion *constructIndexNode(int index)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080048{
Jamie Madill6ba6ead2015-05-04 14:21:21 -040049 TConstantUnion *u = new TConstantUnion[1];
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080050 u[0].setIConst(index);
51
52 TType type(EbtInt, EbpUndefined, EvqConst, 1);
53 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
54 return node;
55}
56
Zhenyao Mo72111912016-07-20 17:45:56 -070057class VariableInitializer : public TIntermTraverser
58{
59 public:
60 VariableInitializer(const InitVariableList &vars)
61 : TIntermTraverser(true, false, false), mVariables(vars), mCodeInserted(false)
62 {
63 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080064
Zhenyao Mo72111912016-07-20 17:45:56 -070065 protected:
66 bool visitBinary(Visit, TIntermBinary *node) override { return false; }
67 bool visitUnary(Visit, TIntermUnary *node) override { return false; }
68 bool visitSelection(Visit, TIntermSelection *node) override { return false; }
69 bool visitLoop(Visit, TIntermLoop *node) override { return false; }
70 bool visitBranch(Visit, TIntermBranch *node) override { return false; }
71
72 bool visitAggregate(Visit visit, TIntermAggregate *node) override;
73
74 private:
75 void insertInitCode(TIntermSequence *sequence);
76
77 const InitVariableList &mVariables;
78 bool mCodeInserted;
79};
80
81// VariableInitializer implementation.
82
83bool VariableInitializer::visitAggregate(Visit visit, TIntermAggregate *node)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080084{
85 bool visitChildren = !mCodeInserted;
86 switch (node->getOp())
87 {
88 case EOpSequence:
89 break;
90 case EOpFunction:
91 {
92 // Function definition.
93 ASSERT(visit == PreVisit);
94 if (node->getName() == "main(")
95 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070096 TIntermSequence *sequence = node->getSequence();
97 ASSERT((sequence->size() == 1) || (sequence->size() == 2));
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080098 TIntermAggregate *body = NULL;
Zhenyao Moe40d1e92014-07-16 17:40:36 -070099 if (sequence->size() == 1)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800100 {
101 body = new TIntermAggregate(EOpSequence);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700102 sequence->push_back(body);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800103 }
104 else
105 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700106 body = (*sequence)[1]->getAsAggregate();
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800107 }
108 ASSERT(body);
109 insertInitCode(body->getSequence());
110 mCodeInserted = true;
111 }
112 break;
113 }
114 default:
115 visitChildren = false;
116 break;
117 }
118 return visitChildren;
119}
120
Zhenyao Mo72111912016-07-20 17:45:56 -0700121void VariableInitializer::insertInitCode(TIntermSequence *sequence)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800122{
123 for (size_t ii = 0; ii < mVariables.size(); ++ii)
124 {
Zhenyao Mo72111912016-07-20 17:45:56 -0700125 const sh::ShaderVariable &var = mVariables[ii];
126 ASSERT(!var.isStruct());
127 TType type = sh::ConvertShaderVariableTypeToTType(var.type);
128 TString name = TString(var.name.c_str());
129 if (var.isArray())
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800130 {
Zhenyao Mo72111912016-07-20 17:45:56 -0700131 size_t pos = name.find_last_of('[');
132 if (pos != TString::npos)
133 name = name.substr(0, pos);
134 for (int index = static_cast<int>(var.arraySize) - 1; index >= 0; --index)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800135 {
136 TIntermBinary *assign = new TIntermBinary(EOpAssign);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700137 sequence->insert(sequence->begin(), assign);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800138
139 TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
Zhenyao Mo72111912016-07-20 17:45:56 -0700140 TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800141 indexDirect->setLeft(symbol);
142 TIntermConstantUnion *indexNode = constructIndexNode(index);
143 indexDirect->setRight(indexNode);
144
145 assign->setLeft(indexDirect);
146
Zhenyao Mo72111912016-07-20 17:45:56 -0700147 TIntermConstantUnion *zeroConst = constructConstUnionNode(type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800148 assign->setRight(zeroConst);
149 }
150 }
151 else
152 {
153 TIntermBinary *assign = new TIntermBinary(EOpAssign);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700154 sequence->insert(sequence->begin(), assign);
Zhenyao Mo72111912016-07-20 17:45:56 -0700155 TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800156 assign->setLeft(symbol);
Zhenyao Mo72111912016-07-20 17:45:56 -0700157 TIntermConstantUnion *zeroConst = constructConstUnionNode(type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800158 assign->setRight(zeroConst);
159 }
160
161 }
162}
163
Zhenyao Mo72111912016-07-20 17:45:56 -0700164} // namespace anonymous
165
166void InitializeVariables(TIntermNode *root, const InitVariableList &vars)
167{
168 VariableInitializer initializer(vars);
169 root->traverse(&initializer);
170}