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/Name.h"
8 #include "common/debug.h"
9 #include "compiler/translator/tree_util/IntermTraverse.h"
10
11 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 emitImpl(out);
69 }
70
71 template <typename T>
emitImpl(T & out) const72 void Name::emitImpl(T &out) const
73 {
74 switch (mSymbolType)
75 {
76 case SymbolType::BuiltIn:
77 ASSERT(!mRawName.empty());
78 out << mRawName;
79 break;
80
81 case SymbolType::UserDefined:
82 ASSERT(!mRawName.empty());
83 if (mRawName != "main")
84 {
85 out << kUserDefinedNamePrefix << mRawName;
86 }
87 else
88 {
89 out << mRawName;
90 }
91 break;
92
93 case SymbolType::AngleInternal:
94 ASSERT(!mRawName.empty());
95 if (mRawName.beginsWith(kAngleInternalPrefix))
96 {
97 out << mRawName;
98 }
99 else
100 {
101 out << kAngleInternalPrefix << '_' << mRawName;
102 }
103 break;
104
105 case SymbolType::Empty:
106 UNREACHABLE();
107 break;
108 }
109 }
110
operator <<(std::ostream & out,const Name & name)111 std::ostream &operator<<(std::ostream &out, const Name &name)
112 {
113 name.emitImpl(out);
114 return out;
115 }
116
117 ////////////////////////////////////////////////////////////////////////////////
118
119 namespace
120 {
121
122 // NOTE: This matches more things than FindSymbolNode.
123 class ExpressionContainsNameVisitor : public TIntermTraverser
124 {
125 Name mName;
126 bool mFoundName = false;
127
128 public:
ExpressionContainsNameVisitor(const Name & name)129 ExpressionContainsNameVisitor(const Name &name)
130 : TIntermTraverser(true, false, false), mName(name)
131 {}
132
foundName() const133 bool foundName() const { return mFoundName; }
134
visitSymbol(TIntermSymbol * node)135 void visitSymbol(TIntermSymbol *node) override
136 {
137 if (Name(node->variable()) == mName)
138 {
139 mFoundName = true;
140 }
141 }
142
visitSwizzle(Visit,TIntermSwizzle *)143 bool visitSwizzle(Visit, TIntermSwizzle *) override { return !mFoundName; }
144
visitBinary(Visit visit,TIntermBinary * node)145 bool visitBinary(Visit visit, TIntermBinary *node) override { return !mFoundName; }
146
visitUnary(Visit visit,TIntermUnary * node)147 bool visitUnary(Visit visit, TIntermUnary *node) override { return !mFoundName; }
148
visitTernary(Visit visit,TIntermTernary * node)149 bool visitTernary(Visit visit, TIntermTernary *node) override { return !mFoundName; }
150
visitAggregate(Visit visit,TIntermAggregate * node)151 bool visitAggregate(Visit visit, TIntermAggregate *node) override
152 {
153 if (node->isConstructor())
154 {
155 const TType &type = node->getType();
156 const TStructure *structure = type.getStruct();
157 if (structure && Name(*structure) == mName)
158 {
159 mFoundName = true;
160 }
161 }
162 else
163 {
164 const TFunction *func = node->getFunction();
165 if (func && Name(*func) == mName)
166 {
167 mFoundName = true;
168 }
169 }
170 return !mFoundName;
171 }
172
visitIfElse(Visit visit,TIntermIfElse * node)173 bool visitIfElse(Visit visit, TIntermIfElse *node) override
174 {
175 UNREACHABLE();
176 return false;
177 }
178
visitSwitch(Visit,TIntermSwitch *)179 bool visitSwitch(Visit, TIntermSwitch *) override
180 {
181 UNREACHABLE();
182 return false;
183 }
visitCase(Visit,TIntermCase *)184 bool visitCase(Visit, TIntermCase *) override
185 {
186 UNREACHABLE();
187 return false;
188 }
189
visitFunctionPrototype(TIntermFunctionPrototype *)190 void visitFunctionPrototype(TIntermFunctionPrototype *) override { UNREACHABLE(); }
191
visitFunctionDefinition(Visit,TIntermFunctionDefinition *)192 bool visitFunctionDefinition(Visit, TIntermFunctionDefinition *) override
193 {
194 UNREACHABLE();
195 return false;
196 }
197
visitBlock(Visit,TIntermBlock *)198 bool visitBlock(Visit, TIntermBlock *) override
199 {
200 UNREACHABLE();
201 return false;
202 }
203
visitGlobalQualifierDeclaration(Visit,TIntermGlobalQualifierDeclaration *)204 bool visitGlobalQualifierDeclaration(Visit, TIntermGlobalQualifierDeclaration *) override
205 {
206 UNREACHABLE();
207 return false;
208 }
209
visitDeclaration(Visit,TIntermDeclaration *)210 bool visitDeclaration(Visit, TIntermDeclaration *) override
211 {
212 UNREACHABLE();
213 return false;
214 }
215
visitLoop(Visit,TIntermLoop *)216 bool visitLoop(Visit, TIntermLoop *) override
217 {
218 UNREACHABLE();
219 return false;
220 }
221
visitBranch(Visit,TIntermBranch *)222 bool visitBranch(Visit, TIntermBranch *) override
223 {
224 UNREACHABLE();
225 return false;
226 }
227
visitPreprocessorDirective(TIntermPreprocessorDirective *)228 void visitPreprocessorDirective(TIntermPreprocessorDirective *) override { UNREACHABLE(); }
229 };
230
231 } // anonymous namespace
232
ExpressionContainsName(const Name & name,TIntermTyped & node)233 bool ExpressionContainsName(const Name &name, TIntermTyped &node)
234 {
235 ExpressionContainsNameVisitor visitor(name);
236 node.traverse(&visitor);
237 return visitor.foundName();
238 }
239
240 } // namespace sh
241