• 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 "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