blob: 21f00936eb8202f3ed4334540fc09ba65a76e630 [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];
Zhenyao Mo72111912016-07-20 17:45:56 -0700126 TString name = TString(var.name.c_str());
127 if (var.isArray())
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800128 {
Zhenyao Mof9312682016-07-22 12:51:31 -0700129 TType type = sh::ConvertShaderVariableTypeToTType(var.type);
Zhenyao Mo72111912016-07-20 17:45:56 -0700130 size_t pos = name.find_last_of('[');
131 if (pos != TString::npos)
132 name = name.substr(0, pos);
133 for (int index = static_cast<int>(var.arraySize) - 1; index >= 0; --index)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800134 {
135 TIntermBinary *assign = new TIntermBinary(EOpAssign);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700136 sequence->insert(sequence->begin(), assign);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800137
138 TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
Zhenyao Mo72111912016-07-20 17:45:56 -0700139 TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800140 indexDirect->setLeft(symbol);
141 TIntermConstantUnion *indexNode = constructIndexNode(index);
142 indexDirect->setRight(indexNode);
143
144 assign->setLeft(indexDirect);
145
Zhenyao Mo72111912016-07-20 17:45:56 -0700146 TIntermConstantUnion *zeroConst = constructConstUnionNode(type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800147 assign->setRight(zeroConst);
148 }
149 }
Zhenyao Mof9312682016-07-22 12:51:31 -0700150 else if (var.isStruct())
151 {
152 TFieldList *fields = new TFieldList;
153 TSourceLoc loc;
154 for (auto field : var.fields)
155 {
156 fields->push_back(new TField(nullptr, new TString(field.name.c_str()), loc));
157 }
158 TStructure *structure = new TStructure(new TString(var.structName.c_str()), fields);
159 TType type;
160 type.setStruct(structure);
Jamie Madillc0513722016-07-22 23:20:59 -0400161 for (int fieldIndex = 0; fieldIndex < static_cast<int>(var.fields.size()); ++fieldIndex)
Zhenyao Mof9312682016-07-22 12:51:31 -0700162 {
163 TIntermBinary *assign = new TIntermBinary(EOpAssign);
164 sequence->insert(sequence->begin(), assign);
165
166 TIntermBinary *indexDirectStruct = new TIntermBinary(EOpIndexDirectStruct);
167 TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
168 indexDirectStruct->setLeft(symbol);
Jamie Madillc0513722016-07-22 23:20:59 -0400169 TIntermConstantUnion *indexNode = constructIndexNode(fieldIndex);
Zhenyao Mof9312682016-07-22 12:51:31 -0700170 indexDirectStruct->setRight(indexNode);
171 assign->setLeft(indexDirectStruct);
172
Jamie Madillc0513722016-07-22 23:20:59 -0400173 const sh::ShaderVariable &field = var.fields[fieldIndex];
Zhenyao Mof9312682016-07-22 12:51:31 -0700174 TType fieldType = sh::ConvertShaderVariableTypeToTType(field.type);
175 TIntermConstantUnion *zeroConst = constructConstUnionNode(fieldType);
176 assign->setRight(zeroConst);
177 }
178 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800179 else
180 {
Zhenyao Mof9312682016-07-22 12:51:31 -0700181 TType type = sh::ConvertShaderVariableTypeToTType(var.type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800182 TIntermBinary *assign = new TIntermBinary(EOpAssign);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700183 sequence->insert(sequence->begin(), assign);
Zhenyao Mo72111912016-07-20 17:45:56 -0700184 TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800185 assign->setLeft(symbol);
Zhenyao Mo72111912016-07-20 17:45:56 -0700186 TIntermConstantUnion *zeroConst = constructConstUnionNode(type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800187 assign->setRight(zeroConst);
188 }
189
190 }
191}
192
Zhenyao Mo72111912016-07-20 17:45:56 -0700193} // namespace anonymous
194
195void InitializeVariables(TIntermNode *root, const InitVariableList &vars)
196{
197 VariableInitializer initializer(vars);
198 root->traverse(&initializer);
199}