blob: 833238520e1901375685b5c08418d1a3952c7a91 [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 -070017class VariableInitializer : public TIntermTraverser
18{
19 public:
20 VariableInitializer(const InitVariableList &vars)
21 : TIntermTraverser(true, false, false), mVariables(vars), mCodeInserted(false)
22 {
23 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080024
Zhenyao Mo72111912016-07-20 17:45:56 -070025 protected:
26 bool visitBinary(Visit, TIntermBinary *node) override { return false; }
27 bool visitUnary(Visit, TIntermUnary *node) override { return false; }
28 bool visitSelection(Visit, TIntermSelection *node) override { return false; }
29 bool visitLoop(Visit, TIntermLoop *node) override { return false; }
30 bool visitBranch(Visit, TIntermBranch *node) override { return false; }
31
32 bool visitAggregate(Visit visit, TIntermAggregate *node) override;
33
34 private:
35 void insertInitCode(TIntermSequence *sequence);
36
37 const InitVariableList &mVariables;
38 bool mCodeInserted;
39};
40
41// VariableInitializer implementation.
42
43bool VariableInitializer::visitAggregate(Visit visit, TIntermAggregate *node)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080044{
45 bool visitChildren = !mCodeInserted;
46 switch (node->getOp())
47 {
48 case EOpSequence:
49 break;
50 case EOpFunction:
51 {
52 // Function definition.
53 ASSERT(visit == PreVisit);
54 if (node->getName() == "main(")
55 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070056 TIntermSequence *sequence = node->getSequence();
57 ASSERT((sequence->size() == 1) || (sequence->size() == 2));
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080058 TIntermAggregate *body = NULL;
Zhenyao Moe40d1e92014-07-16 17:40:36 -070059 if (sequence->size() == 1)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080060 {
61 body = new TIntermAggregate(EOpSequence);
Zhenyao Moe40d1e92014-07-16 17:40:36 -070062 sequence->push_back(body);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080063 }
64 else
65 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -070066 body = (*sequence)[1]->getAsAggregate();
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080067 }
68 ASSERT(body);
69 insertInitCode(body->getSequence());
70 mCodeInserted = true;
71 }
72 break;
73 }
74 default:
75 visitChildren = false;
76 break;
77 }
78 return visitChildren;
79}
80
Zhenyao Mo72111912016-07-20 17:45:56 -070081void VariableInitializer::insertInitCode(TIntermSequence *sequence)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080082{
Corentin Wallez509e4562016-08-25 14:55:44 -040083 for (const auto &var : mVariables)
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080084 {
Zhenyao Mo72111912016-07-20 17:45:56 -070085 TString name = TString(var.name.c_str());
Corentin Wallez509e4562016-08-25 14:55:44 -040086 TType type = sh::GetShaderVariableType(var);
87
88 // Assign the array elements one by one to keep the AST compatible with ESSL 1.00 which
89 // doesn't have array assignment.
Zhenyao Mo72111912016-07-20 17:45:56 -070090 if (var.isArray())
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080091 {
Zhenyao Mo72111912016-07-20 17:45:56 -070092 size_t pos = name.find_last_of('[');
93 if (pos != TString::npos)
Corentin Wallez509e4562016-08-25 14:55:44 -040094 {
Zhenyao Mo72111912016-07-20 17:45:56 -070095 name = name.substr(0, pos);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -080096 }
Corentin Wallez509e4562016-08-25 14:55:44 -040097 TType elementType = type;
98 elementType.clearArrayness();
Zhenyao Mof9312682016-07-22 12:51:31 -070099
Corentin Wallez509e4562016-08-25 14:55:44 -0400100 for (unsigned int i = 0; i < var.arraySize; ++i)
101 {
Olli Etuaho3272a6d2016-08-29 17:54:50 +0300102 TIntermSymbol *arraySymbol = new TIntermSymbol(0, name, type);
103 TIntermBinary *element = new TIntermBinary(EOpIndexDirect, arraySymbol,
104 TIntermTyped::CreateIndexNode(i));
Zhenyao Mof9312682016-07-22 12:51:31 -0700105
Corentin Wallez509e4562016-08-25 14:55:44 -0400106 TIntermTyped *zero = TIntermTyped::CreateZero(elementType);
107 TIntermBinary *assignment = new TIntermBinary(EOpAssign, element, zero);
108
109 sequence->insert(sequence->begin(), assignment);
Zhenyao Mof9312682016-07-22 12:51:31 -0700110 }
111 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800112 else
113 {
Zhenyao Mo72111912016-07-20 17:45:56 -0700114 TIntermSymbol *symbol = new TIntermSymbol(0, name, type);
Corentin Wallez509e4562016-08-25 14:55:44 -0400115 TIntermTyped *zero = TIntermTyped::CreateZero(type);
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800116
Corentin Wallez509e4562016-08-25 14:55:44 -0400117 TIntermBinary *assign = new TIntermBinary(EOpAssign, symbol, zero);
118 sequence->insert(sequence->begin(), assign);
119 }
Zhenyao Mo4a667fe2014-02-11 12:35:01 -0800120 }
121}
122
Zhenyao Mo72111912016-07-20 17:45:56 -0700123} // namespace anonymous
124
125void InitializeVariables(TIntermNode *root, const InitVariableList &vars)
126{
127 VariableInitializer initializer(vars);
128 root->traverse(&initializer);
129}