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/TranslatorMetalDirect/AstHelpers.h"
10 #include "compiler/translator/TranslatorMetalDirect/SeparateCompoundStructDeclarations.h"
11 #include "compiler/translator/tree_ops/SeparateDeclarations.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("__unnamed").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 instanceType->setQualifier(type.getQualifier());
59 auto *instanceVar =
60 new TVariable(mSymbolTable, var.name(), instanceType, symbolType, var.extensions());
61
62 TIntermSequence replacements;
63 replacements.push_back(new TIntermSymbol(structVar));
64
65 TIntermSymbol *instanceSymbol = new TIntermSymbol(instanceVar);
66 TIntermNode *instanceReplacement = instanceSymbol;
67 if (declaration.initExpr)
68 {
69 instanceReplacement =
70 new TIntermBinary(EOpInitialize, instanceSymbol, declaration.initExpr);
71 }
72 replacements.push_back(instanceReplacement);
73
74 replacementMap[declaration.symbol.uniqueId().get()] = instanceSymbol;
75 mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(
76 declNode, declNode->getChildNode(0), std::move(replacements)));
77 }
78
79 return false;
80 }
81
visitSymbol(TIntermSymbol * decl)82 void visitSymbol(TIntermSymbol *decl) override
83 {
84 auto symbol = replacementMap.find(decl->uniqueId().get());
85 if (symbol != replacementMap.end())
86 {
87 queueReplacement(symbol->second->deepCopy(), OriginalNode::IS_DROPPED);
88 }
89 }
90 };
91
92 } // anonymous namespace
93
94 ////////////////////////////////////////////////////////////////////////////////
95
SeparateCompoundStructDeclarations(TCompiler & compiler,IdGen & idGen,TIntermBlock & root)96 bool sh::SeparateCompoundStructDeclarations(TCompiler &compiler, IdGen &idGen, TIntermBlock &root)
97 {
98 Separator separator(compiler.getSymbolTable(), idGen);
99 root.traverse(&separator);
100 if (!separator.updateTree(&compiler, &root))
101 {
102 return false;
103 }
104
105 if (!SeparateDeclarations(&compiler, &root))
106 {
107 return false;
108 }
109
110 return true;
111 }
112