• 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 <cstring>
8 #include <unordered_map>
9 #include <unordered_set>
10 
11 #include "compiler/translator/TranslatorMetalDirect/DiscoverDependentFunctions.h"
12 #include "compiler/translator/TranslatorMetalDirect/DiscoverEnclosingFunctionTraverser.h"
13 #include "compiler/translator/TranslatorMetalDirect/MapFunctionsToDefinitions.h"
14 
15 using namespace sh;
16 
17 ////////////////////////////////////////////////////////////////////////////////
18 
19 namespace
20 {
21 
22 class Discoverer : public DiscoverEnclosingFunctionTraverser
23 {
24   private:
25     const std::function<bool(const TVariable &)> &mVars;
26     const FunctionToDefinition &mFuncToDef;
27     std::unordered_set<const TFunction *> mNonDepFunctions;
28 
29   public:
30     std::unordered_set<const TFunction *> mDepFunctions;
31 
32   public:
Discoverer(const std::function<bool (const TVariable &)> & vars,const FunctionToDefinition & funcToDef)33     Discoverer(const std::function<bool(const TVariable &)> &vars,
34                const FunctionToDefinition &funcToDef)
35         : DiscoverEnclosingFunctionTraverser(true, false, true), mVars(vars), mFuncToDef(funcToDef)
36     {}
37 
visitSymbol(TIntermSymbol * symbolNode)38     void visitSymbol(TIntermSymbol *symbolNode) override
39     {
40         const TVariable &var = symbolNode->variable();
41         if (!mVars(var))
42         {
43             return;
44         }
45         const TFunction *owner = discoverEnclosingFunction(symbolNode);
46         ASSERT(owner);
47         mDepFunctions.insert(owner);
48     }
49 
visitAggregate(Visit visit,TIntermAggregate * aggregateNode)50     bool visitAggregate(Visit visit, TIntermAggregate *aggregateNode) override
51     {
52         if (visit != Visit::PreVisit)
53         {
54             return true;
55         }
56 
57         if (!aggregateNode->isConstructor())
58         {
59             const TFunction *func = aggregateNode->getFunction();
60 
61             if (mNonDepFunctions.find(func) != mNonDepFunctions.end())
62             {
63                 return true;
64             }
65 
66             if (mDepFunctions.find(func) == mDepFunctions.end())
67             {
68                 auto it = mFuncToDef.find(func);
69                 if (it == mFuncToDef.end())
70                 {
71                     return true;
72                 }
73 
74                 // Recursion is banned in GLSL, so I believe AngleIR has this property too.
75                 // This implementation assumes (direct and mutual) recursion is prohibited.
76                 TIntermFunctionDefinition &funcDefNode = *it->second;
77                 funcDefNode.traverse(this);
78                 if (mNonDepFunctions.find(func) != mNonDepFunctions.end())
79                 {
80                     return true;
81                 }
82                 ASSERT(mDepFunctions.find(func) != mDepFunctions.end());
83             }
84 
85             const TFunction *owner = discoverEnclosingFunction(aggregateNode);
86             ASSERT(owner);
87             mDepFunctions.insert(owner);
88         }
89 
90         return true;
91     }
92 
visitFunctionDefinition(Visit visit,TIntermFunctionDefinition * funcDefNode)93     bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *funcDefNode) override
94     {
95         const TFunction *func = funcDefNode->getFunction();
96 
97         if (visit != Visit::PostVisit)
98         {
99             if (mDepFunctions.find(func) != mDepFunctions.end())
100             {
101                 return false;
102             }
103 
104             if (mNonDepFunctions.find(func) != mNonDepFunctions.end())
105             {
106                 return false;
107             }
108 
109             return true;
110         }
111 
112         if (mDepFunctions.find(func) == mDepFunctions.end())
113         {
114             mNonDepFunctions.insert(func);
115         }
116 
117         return true;
118     }
119 };
120 
121 }  // namespace
122 
DiscoverDependentFunctions(TIntermBlock & root,const std::function<bool (const TVariable &)> & vars)123 std::unordered_set<const TFunction *> sh::DiscoverDependentFunctions(
124     TIntermBlock &root,
125     const std::function<bool(const TVariable &)> &vars)
126 {
127     const FunctionToDefinition funcToDef = MapFunctionsToDefinitions(root);
128     Discoverer discoverer(vars, funcToDef);
129     root.traverse(&discoverer);
130     return std::move(discoverer.mDepFunctions);
131 }
132