• 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/msl/Name.h"
8 #include "common/debug.h"
9 #include "compiler/translator/tree_util/IntermTraverse.h"
10 
11 using namespace sh;
12 
13 ////////////////////////////////////////////////////////////////////////////////
14 
15 template <typename T>
GetName(T const & object)16 static ImmutableString GetName(T const &object)
17 {
18     if (object.symbolType() == SymbolType::Empty)
19     {
20         return kEmptyImmutableString;
21     }
22     return object.name();
23 }
24 
Name(const TField & field)25 Name::Name(const TField &field) : Name(GetName(field), field.symbolType()) {}
26 
Name(const TSymbol & symbol)27 Name::Name(const TSymbol &symbol) : Name(GetName(symbol), symbol.symbolType()) {}
28 
operator ==(const Name & other) const29 bool Name::operator==(const Name &other) const
30 {
31     return mRawName == other.mRawName && mSymbolType == other.mSymbolType;
32 }
33 
operator !=(const Name & other) const34 bool Name::operator!=(const Name &other) const
35 {
36     return !(*this == other);
37 }
38 
operator <(const Name & other) const39 bool Name::operator<(const Name &other) const
40 {
41     if (mRawName < other.mRawName)
42     {
43         return true;
44     }
45     if (other.mRawName < mRawName)
46     {
47         return false;
48     }
49     return mSymbolType < other.mSymbolType;
50 }
51 
empty() const52 bool Name::empty() const
53 {
54     return mSymbolType == SymbolType::Empty;
55 }
56 
beginsWith(const Name & prefix) const57 bool Name::beginsWith(const Name &prefix) const
58 {
59     if (mSymbolType != prefix.mSymbolType)
60     {
61         return false;
62     }
63     return mRawName.beginsWith(prefix.mRawName);
64 }
65 
emit(TInfoSinkBase & out) const66 void Name::emit(TInfoSinkBase &out) const
67 {
68     switch (mSymbolType)
69     {
70         case SymbolType::BuiltIn:
71             ASSERT(!mRawName.empty());
72             out << mRawName;
73             break;
74 
75         case SymbolType::UserDefined:
76             ASSERT(!mRawName.empty());
77             if (mRawName != "main")
78             {
79                 out << kUserDefinedNamePrefix << mRawName;
80             }
81             else
82             {
83                 out << mRawName;
84             }
85             break;
86 
87         case SymbolType::AngleInternal:
88             ASSERT(!mRawName.empty());
89             if (mRawName.beginsWith(kAngleInternalPrefix))
90             {
91                 out << mRawName;
92             }
93             else if (mRawName[0] != '_')
94             {
95                 out << kAngleInternalPrefix << '_' << mRawName;
96             }
97             else
98             {
99                 out << kAngleInternalPrefix << mRawName;
100             }
101             break;
102 
103         case SymbolType::Empty:
104             UNREACHABLE();
105             break;
106     }
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 
111 namespace
112 {
113 
114 // NOTE: This matches more things than FindSymbolNode.
115 class ExpressionContainsNameVisitor : public TIntermTraverser
116 {
117     Name mName;
118     bool mFoundName = false;
119 
120   public:
ExpressionContainsNameVisitor(const Name & name)121     ExpressionContainsNameVisitor(const Name &name)
122         : TIntermTraverser(true, false, false), mName(name)
123     {}
124 
foundName() const125     bool foundName() const { return mFoundName; }
126 
visitSymbol(TIntermSymbol * node)127     void visitSymbol(TIntermSymbol *node) override
128     {
129         if (Name(node->variable()) == mName)
130         {
131             mFoundName = true;
132         }
133     }
134 
visitSwizzle(Visit,TIntermSwizzle *)135     bool visitSwizzle(Visit, TIntermSwizzle *) override { return !mFoundName; }
136 
visitBinary(Visit visit,TIntermBinary * node)137     bool visitBinary(Visit visit, TIntermBinary *node) override { return !mFoundName; }
138 
visitUnary(Visit visit,TIntermUnary * node)139     bool visitUnary(Visit visit, TIntermUnary *node) override { return !mFoundName; }
140 
visitTernary(Visit visit,TIntermTernary * node)141     bool visitTernary(Visit visit, TIntermTernary *node) override { return !mFoundName; }
142 
visitAggregate(Visit visit,TIntermAggregate * node)143     bool visitAggregate(Visit visit, TIntermAggregate *node) override
144     {
145         if (node->isConstructor())
146         {
147             const TType &type           = node->getType();
148             const TStructure *structure = type.getStruct();
149             if (structure && Name(*structure) == mName)
150             {
151                 mFoundName = true;
152             }
153         }
154         else
155         {
156             const TFunction *func = node->getFunction();
157             if (func && Name(*func) == mName)
158             {
159                 mFoundName = true;
160             }
161         }
162         return !mFoundName;
163     }
164 
visitIfElse(Visit visit,TIntermIfElse * node)165     bool visitIfElse(Visit visit, TIntermIfElse *node) override
166     {
167         UNREACHABLE();
168         return false;
169     }
170 
visitSwitch(Visit,TIntermSwitch *)171     bool visitSwitch(Visit, TIntermSwitch *) override
172     {
173         UNREACHABLE();
174         return false;
175     }
visitCase(Visit,TIntermCase *)176     bool visitCase(Visit, TIntermCase *) override
177     {
178         UNREACHABLE();
179         return false;
180     }
181 
visitFunctionPrototype(TIntermFunctionPrototype *)182     void visitFunctionPrototype(TIntermFunctionPrototype *) override { UNREACHABLE(); }
183 
visitFunctionDefinition(Visit,TIntermFunctionDefinition *)184     bool visitFunctionDefinition(Visit, TIntermFunctionDefinition *) override
185     {
186         UNREACHABLE();
187         return false;
188     }
189 
visitBlock(Visit,TIntermBlock *)190     bool visitBlock(Visit, TIntermBlock *) override
191     {
192         UNREACHABLE();
193         return false;
194     }
195 
visitGlobalQualifierDeclaration(Visit,TIntermGlobalQualifierDeclaration *)196     bool visitGlobalQualifierDeclaration(Visit, TIntermGlobalQualifierDeclaration *) override
197     {
198         UNREACHABLE();
199         return false;
200     }
201 
visitDeclaration(Visit,TIntermDeclaration *)202     bool visitDeclaration(Visit, TIntermDeclaration *) override
203     {
204         UNREACHABLE();
205         return false;
206     }
207 
visitLoop(Visit,TIntermLoop *)208     bool visitLoop(Visit, TIntermLoop *) override
209     {
210         UNREACHABLE();
211         return false;
212     }
213 
visitBranch(Visit,TIntermBranch *)214     bool visitBranch(Visit, TIntermBranch *) override
215     {
216         UNREACHABLE();
217         return false;
218     }
219 
visitPreprocessorDirective(TIntermPreprocessorDirective *)220     void visitPreprocessorDirective(TIntermPreprocessorDirective *) override { UNREACHABLE(); }
221 };
222 
223 }  // anonymous namespace
224 
ExpressionContainsName(const Name & name,TIntermTyped & node)225 bool sh::ExpressionContainsName(const Name &name, TIntermTyped &node)
226 {
227     ExpressionContainsNameVisitor visitor(name);
228     node.traverse(&visitor);
229     return visitor.foundName();
230 }
231