• 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/msl/AstHelpers.h"
10 #include "compiler/translator/tree_ops/SeparateDeclarations.h"
11 #include "compiler/translator/tree_ops/msl/SeparateCompoundStructDeclarations.h"
12 #include "compiler/translator/tree_util/IntermTraverse.h"
13 
14 using namespace sh;
15 
16 ////////////////////////////////////////////////////////////////////////////////
17 
18 namespace
19 {
20 
21 class Separator : public TIntermTraverser
22 {
23   public:
24     std::unordered_map<int, TIntermSymbol *> replacementMap;
Separator(TSymbolTable & symbolTable,IdGen & idGen)25     Separator(TSymbolTable &symbolTable, IdGen &idGen)
26         : TIntermTraverser(false, false, true, &symbolTable), mIdGen(idGen)
27     {}
28     IdGen &mIdGen;
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             TVariable *structVar        = nullptr;
41             TType *instanceType         = nullptr;
42             // Name unnamed inline structs
43             if (structure->symbolType() == SymbolType::Empty)
44             {
45                 const TStructure *structDefn =
46                     new TStructure(mSymbolTable, mIdGen.createNewName().rawName(),
47                                    &structure->fields(), SymbolType::AngleInternal);
48                 structVar    = new TVariable(mSymbolTable, ImmutableString(""),
49                                              new TType(structDefn, true), SymbolType::Empty);
50                 instanceType = new TType(structDefn, false);
51             }
52             else
53             {
54                 structVar    = new TVariable(mSymbolTable, ImmutableString(""),
55                                              new TType(structure, true), SymbolType::Empty);
56                 instanceType = new TType(structure, false);
57             }
58             if (type.isArray())
59             {
60                 instanceType->makeArrays(type.getArraySizes());
61             }
62             instanceType->setQualifier(type.getQualifier());
63             auto *instanceVar =
64                 new TVariable(mSymbolTable, var.name(), instanceType, symbolType, var.extensions());
65 
66             TIntermSequence replacements;
67             replacements.push_back(new TIntermDeclaration({structVar}));
68 
69             TIntermSymbol *instanceSymbol    = new TIntermSymbol(instanceVar);
70             TIntermDeclaration *instanceDecl = new TIntermDeclaration;
71             if (declaration.initExpr)
72             {
73                 instanceDecl->appendDeclarator(new TIntermBinary(
74                     TOperator::EOpInitialize, instanceSymbol, declaration.initExpr));
75             }
76             else
77             {
78                 instanceDecl->appendDeclarator(instanceSymbol);
79             }
80             replacements.push_back(instanceDecl);
81 
82             replacementMap[declaration.symbol.uniqueId().get()] = instanceSymbol;
83             ASSERT(getParentNode() != nullptr);
84             ASSERT(getParentNode()->getAsBlock() != nullptr);
85             mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(
86                 getParentNode()->getAsBlock(), declNode, std::move(replacements)));
87         }
88 
89         return false;
90     }
91 
visitSymbol(TIntermSymbol * decl)92     void visitSymbol(TIntermSymbol *decl) override
93     {
94         auto symbol = replacementMap.find(decl->uniqueId().get());
95         if (symbol != replacementMap.end())
96         {
97             queueReplacement(symbol->second->deepCopy(), OriginalNode::IS_DROPPED);
98         }
99     }
100 };
101 
102 }  // anonymous namespace
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 
SeparateCompoundStructDeclarations(TCompiler & compiler,IdGen & idGen,TIntermBlock & root,TSymbolTable * symbolTable)106 bool sh::SeparateCompoundStructDeclarations(TCompiler &compiler,
107                                             IdGen &idGen,
108                                             TIntermBlock &root,
109                                             TSymbolTable *symbolTable)
110 {
111     Separator separator(compiler.getSymbolTable(), idGen);
112     root.traverse(&separator);
113     if (!separator.updateTree(&compiler, &root))
114     {
115         return false;
116     }
117 
118     if (!SeparateDeclarations(&compiler, &root, symbolTable))
119     {
120         return false;
121     }
122 
123     return true;
124 }
125