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