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 "compiler/translator/TranslatorMetalDirect/RewriteGlobalQualifierDecls.h"
8 #include "compiler/translator/TranslatorMetalDirect/IntermRebuild.h"
9
10 using namespace sh;
11
12 namespace
13 {
14
15 class FindDeclaredGlobals : public TIntermRebuild
16 {
17 public:
18 std::unordered_set<const TVariable *> mDeclaredGlobals;
19
FindDeclaredGlobals(TCompiler & compiler)20 FindDeclaredGlobals(TCompiler &compiler) : TIntermRebuild(compiler, true, false) {}
21
visitDeclarationPre(TIntermDeclaration & declNode)22 PreResult visitDeclarationPre(TIntermDeclaration &declNode) override
23 {
24 TIntermNode *declaratorNode = declNode.getChildNode(0);
25 TIntermSymbol *symbolNode = nullptr;
26
27 if (TIntermBinary *initNode = declaratorNode->getAsBinaryNode())
28 {
29 symbolNode = initNode->getLeft()->getAsSymbolNode();
30 }
31 else
32 {
33 symbolNode = declaratorNode->getAsSymbolNode();
34 }
35
36 ASSERT(symbolNode);
37 const TVariable &var = symbolNode->variable();
38
39 mDeclaredGlobals.insert(&var);
40
41 return {declNode, VisitBits::Neither};
42 }
43
visitFunctionDefinitionPre(TIntermFunctionDefinition & node)44 PreResult visitFunctionDefinitionPre(TIntermFunctionDefinition &node) override
45 {
46 return {node, VisitBits::Neither};
47 }
48 };
49
50 class Rewriter : public TIntermRebuild
51 {
52 const std::unordered_set<const TVariable *> &mDeclaredGlobals;
53 Invariants &mOutInvariants;
54
55 public:
Rewriter(TCompiler & compiler,const std::unordered_set<const TVariable * > & declaredGlobals,Invariants & outInvariants)56 Rewriter(TCompiler &compiler,
57 const std::unordered_set<const TVariable *> &declaredGlobals,
58 Invariants &outInvariants)
59 : TIntermRebuild(compiler, true, false),
60 mDeclaredGlobals(declaredGlobals),
61 mOutInvariants(outInvariants)
62 {}
63
visitGlobalQualifierDeclarationPre(TIntermGlobalQualifierDeclaration & gqDeclNode)64 PreResult visitGlobalQualifierDeclarationPre(
65 TIntermGlobalQualifierDeclaration &gqDeclNode) override
66 {
67 TIntermSymbol &symbolNode = *gqDeclNode.getSymbol();
68 const TVariable &var = symbolNode.variable();
69
70 if (gqDeclNode.isInvariant())
71 {
72 mOutInvariants.insert(var);
73 }
74
75 if (mDeclaredGlobals.find(&var) == mDeclaredGlobals.end())
76 {
77 return *new TIntermDeclaration{&symbolNode};
78 }
79 return nullptr;
80 }
81
visitDeclarationPre(TIntermDeclaration & node)82 PreResult visitDeclarationPre(TIntermDeclaration &node) override
83 {
84 return {node, VisitBits::Neither};
85 }
86
visitFunctionDefinitionPre(TIntermFunctionDefinition & node)87 PreResult visitFunctionDefinitionPre(TIntermFunctionDefinition &node) override
88 {
89 return {node, VisitBits::Neither};
90 }
91 };
92
93 } // anonymous namespace
94
RewriteGlobalQualifierDecls(TCompiler & compiler,TIntermBlock & root,Invariants & outInvariants)95 bool sh::RewriteGlobalQualifierDecls(TCompiler &compiler,
96 TIntermBlock &root,
97 Invariants &outInvariants)
98 {
99 FindDeclaredGlobals fdg(compiler);
100 if (!fdg.rebuildRoot(root))
101 {
102 UNREACHABLE();
103 return false;
104 }
105
106 Rewriter rewriter(compiler, fdg.mDeclaredGlobals, outInvariants);
107 if (!rewriter.rebuildRoot(root))
108 {
109 return false;
110 }
111
112 return true;
113 }
114