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