• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 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 <algorithm>
8 
9 #include "compiler/translator/tree_ops/SeparateDeclarations.h"
10 #include "compiler/translator/tree_ops/msl/SeparateCompoundStructDeclarations.h"
11 #include "compiler/translator/tree_util/IntermTraverse.h"
12 #include "compiler/translator/tree_util/ReplaceVariable.h"
13 #include "compiler/translator/util.h"
14 
15 using namespace sh;
16 
17 ////////////////////////////////////////////////////////////////////////////////
18 
19 namespace
20 {
21 
22 class Separator : public TIntermTraverser
23 {
24   public:
Separator(TSymbolTable & symbolTable,IdGen & idGen)25     Separator(TSymbolTable &symbolTable, IdGen &idGen)
26         : TIntermTraverser(false, false, true, &symbolTable), mIdGen(idGen)
27     {}
28 
visitDeclaration(Visit,TIntermDeclaration * declNode)29     bool visitDeclaration(Visit, TIntermDeclaration *declNode) override
30     {
31         ASSERT(declNode->getChildCount() == 1);
32         Declaration declaration = ViewDeclaration(*declNode);
33 
34         const TVariable &var        = declaration.symbol.variable();
35         const TType &type           = var.getType();
36         const SymbolType symbolType = var.symbolType();
37         if (type.isStructSpecifier() && symbolType != SymbolType::Empty)
38         {
39             const TStructure *structure = type.getStruct();
40             if (structure->symbolType() == SymbolType::Empty)
41             {
42                 // Name unnamed inline structs.
43                 structure = new TStructure(mSymbolTable, mIdGen.createNewName().rawName(),
44                                            &structure->fields(), SymbolType::AngleInternal);
45             }
46             TVariable *structVar = new TVariable(mSymbolTable, kEmptyImmutableString,
47                                                  new TType(structure, true), SymbolType::Empty);
48             TType *instanceType  = new TType(structure, false);
49             if (type.isArray())
50             {
51                 instanceType->makeArrays(type.getArraySizes());
52             }
53             instanceType->setQualifier(type.getQualifier());
54             auto *instanceVar =
55                 new TVariable(mSymbolTable, var.name(), instanceType, symbolType, var.extensions());
56 
57             TIntermSequence replacements;
58             replacements.push_back(new TIntermDeclaration({structVar}));
59 
60             TIntermSymbol *instanceSymbol    = new TIntermSymbol(instanceVar);
61             TIntermDeclaration *instanceDecl = new TIntermDeclaration;
62             if (declaration.initExpr)
63             {
64                 instanceDecl->appendDeclarator(new TIntermBinary(
65                     TOperator::EOpInitialize, instanceSymbol, declaration.initExpr));
66             }
67             else
68             {
69                 instanceDecl->appendDeclarator(instanceSymbol);
70             }
71             replacements.push_back(instanceDecl);
72 
73             mVariableMap[&declaration.symbol.variable()] = instanceSymbol;
74             ASSERT(getParentNode() != nullptr);
75             ASSERT(getParentNode()->getAsBlock() != nullptr);
76             mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(
77                 getParentNode()->getAsBlock(), declNode, std::move(replacements)));
78         }
79 
80         return false;
81     }
82 
visitSymbol(TIntermSymbol * symbol)83     void visitSymbol(TIntermSymbol *symbol) override
84     {
85         const TVariable *variable = &symbol->variable();
86         if (mVariableMap.count(variable) > 0)
87         {
88             queueAccessChainReplacement(mVariableMap[variable]->deepCopy());
89         }
90     }
91 
92     IdGen &mIdGen;
93     VariableReplacementMap mVariableMap;
94 };
95 
96 }  // anonymous namespace
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 
SeparateCompoundStructDeclarations(TCompiler & compiler,IdGen & idGen,TIntermBlock & root)100 bool sh::SeparateCompoundStructDeclarations(TCompiler &compiler, IdGen &idGen, TIntermBlock &root)
101 {
102     Separator separator(compiler.getSymbolTable(), idGen);
103     root.traverse(&separator);
104     if (!separator.updateTree(&compiler, &root))
105     {
106         return false;
107     }
108 
109     if (!SeparateDeclarations(compiler, root))
110     {
111         return false;
112     }
113 
114     return true;
115 }
116