Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 1 | // |
| 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 Etuaho | d57e0db | 2015-04-24 15:05:08 +0300 | [diff] [blame] | 8 | |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 9 | #include "angle_gl.h" |
Olli Etuaho | d57e0db | 2015-04-24 15:05:08 +0300 | [diff] [blame] | 10 | #include "common/debug.h" |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 11 | #include "compiler/translator/IntermNode.h" |
| 12 | #include "compiler/translator/util.h" |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 13 | |
| 14 | namespace |
| 15 | { |
| 16 | |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 17 | TIntermConstantUnion *constructConstUnionNode(const TType &type) |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 18 | { |
| 19 | TType myType = type; |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 20 | myType.clearArrayness(); |
| 21 | myType.setQualifier(EvqConst); |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 22 | 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 Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 43 | TIntermConstantUnion *node = new TIntermConstantUnion(u, myType); |
| 44 | return node; |
| 45 | } |
| 46 | |
Zhenyao Mo | e40d1e9 | 2014-07-16 17:40:36 -0700 | [diff] [blame] | 47 | TIntermConstantUnion *constructIndexNode(int index) |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 48 | { |
Jamie Madill | 6ba6ead | 2015-05-04 14:21:21 -0400 | [diff] [blame] | 49 | TConstantUnion *u = new TConstantUnion[1]; |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 50 | 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 Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 57 | class VariableInitializer : public TIntermTraverser |
| 58 | { |
| 59 | public: |
| 60 | VariableInitializer(const InitVariableList &vars) |
| 61 | : TIntermTraverser(true, false, false), mVariables(vars), mCodeInserted(false) |
| 62 | { |
| 63 | } |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 64 | |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 65 | 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 | |
| 83 | bool VariableInitializer::visitAggregate(Visit visit, TIntermAggregate *node) |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 84 | { |
| 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 Mo | e40d1e9 | 2014-07-16 17:40:36 -0700 | [diff] [blame] | 96 | TIntermSequence *sequence = node->getSequence(); |
| 97 | ASSERT((sequence->size() == 1) || (sequence->size() == 2)); |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 98 | TIntermAggregate *body = NULL; |
Zhenyao Mo | e40d1e9 | 2014-07-16 17:40:36 -0700 | [diff] [blame] | 99 | if (sequence->size() == 1) |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 100 | { |
| 101 | body = new TIntermAggregate(EOpSequence); |
Zhenyao Mo | e40d1e9 | 2014-07-16 17:40:36 -0700 | [diff] [blame] | 102 | sequence->push_back(body); |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 103 | } |
| 104 | else |
| 105 | { |
Zhenyao Mo | e40d1e9 | 2014-07-16 17:40:36 -0700 | [diff] [blame] | 106 | body = (*sequence)[1]->getAsAggregate(); |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 107 | } |
| 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 Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 121 | void VariableInitializer::insertInitCode(TIntermSequence *sequence) |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 122 | { |
| 123 | for (size_t ii = 0; ii < mVariables.size(); ++ii) |
| 124 | { |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 125 | const sh::ShaderVariable &var = mVariables[ii]; |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 126 | TString name = TString(var.name.c_str()); |
| 127 | if (var.isArray()) |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 128 | { |
Zhenyao Mo | f931268 | 2016-07-22 12:51:31 -0700 | [diff] [blame] | 129 | TType type = sh::ConvertShaderVariableTypeToTType(var.type); |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 130 | 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 Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 134 | { |
| 135 | TIntermBinary *assign = new TIntermBinary(EOpAssign); |
Zhenyao Mo | e40d1e9 | 2014-07-16 17:40:36 -0700 | [diff] [blame] | 136 | sequence->insert(sequence->begin(), assign); |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 137 | |
| 138 | TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect); |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 139 | TIntermSymbol *symbol = new TIntermSymbol(0, name, type); |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 140 | indexDirect->setLeft(symbol); |
| 141 | TIntermConstantUnion *indexNode = constructIndexNode(index); |
| 142 | indexDirect->setRight(indexNode); |
| 143 | |
| 144 | assign->setLeft(indexDirect); |
| 145 | |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 146 | TIntermConstantUnion *zeroConst = constructConstUnionNode(type); |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 147 | assign->setRight(zeroConst); |
| 148 | } |
| 149 | } |
Zhenyao Mo | f931268 | 2016-07-22 12:51:31 -0700 | [diff] [blame] | 150 | 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 Madill | c051372 | 2016-07-22 23:20:59 -0400 | [diff] [blame] | 161 | for (int fieldIndex = 0; fieldIndex < static_cast<int>(var.fields.size()); ++fieldIndex) |
Zhenyao Mo | f931268 | 2016-07-22 12:51:31 -0700 | [diff] [blame] | 162 | { |
| 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 Madill | c051372 | 2016-07-22 23:20:59 -0400 | [diff] [blame] | 169 | TIntermConstantUnion *indexNode = constructIndexNode(fieldIndex); |
Zhenyao Mo | f931268 | 2016-07-22 12:51:31 -0700 | [diff] [blame] | 170 | indexDirectStruct->setRight(indexNode); |
| 171 | assign->setLeft(indexDirectStruct); |
| 172 | |
Jamie Madill | c051372 | 2016-07-22 23:20:59 -0400 | [diff] [blame] | 173 | const sh::ShaderVariable &field = var.fields[fieldIndex]; |
Zhenyao Mo | f931268 | 2016-07-22 12:51:31 -0700 | [diff] [blame] | 174 | TType fieldType = sh::ConvertShaderVariableTypeToTType(field.type); |
| 175 | TIntermConstantUnion *zeroConst = constructConstUnionNode(fieldType); |
| 176 | assign->setRight(zeroConst); |
| 177 | } |
| 178 | } |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 179 | else |
| 180 | { |
Zhenyao Mo | f931268 | 2016-07-22 12:51:31 -0700 | [diff] [blame] | 181 | TType type = sh::ConvertShaderVariableTypeToTType(var.type); |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 182 | TIntermBinary *assign = new TIntermBinary(EOpAssign); |
Zhenyao Mo | e40d1e9 | 2014-07-16 17:40:36 -0700 | [diff] [blame] | 183 | sequence->insert(sequence->begin(), assign); |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 184 | TIntermSymbol *symbol = new TIntermSymbol(0, name, type); |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 185 | assign->setLeft(symbol); |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 186 | TIntermConstantUnion *zeroConst = constructConstUnionNode(type); |
Zhenyao Mo | 4a667fe | 2014-02-11 12:35:01 -0800 | [diff] [blame] | 187 | assign->setRight(zeroConst); |
| 188 | } |
| 189 | |
| 190 | } |
| 191 | } |
| 192 | |
Zhenyao Mo | 7211191 | 2016-07-20 17:45:56 -0700 | [diff] [blame] | 193 | } // namespace anonymous |
| 194 | |
| 195 | void InitializeVariables(TIntermNode *root, const InitVariableList &vars) |
| 196 | { |
| 197 | VariableInitializer initializer(vars); |
| 198 | root->traverse(&initializer); |
| 199 | } |