1 //
2 // Copyright 2017 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 // Symbol.cpp: Symbols representing variables, functions, structures and interface blocks.
7 //
8
9 #if defined(_MSC_VER)
10 # pragma warning(disable : 4718)
11 #endif
12
13 #include "compiler/translator/Symbol.h"
14
15 #include "compiler/translator/ImmutableStringBuilder.h"
16 #include "compiler/translator/SymbolTable.h"
17
18 namespace sh
19 {
20
21 namespace
22 {
23
24 constexpr const ImmutableString kMainName("main");
25 constexpr const ImmutableString kImageLoadName("imageLoad");
26 constexpr const ImmutableString kImageStoreName("imageStore");
27 constexpr const ImmutableString kImageSizeName("imageSize");
28 constexpr const ImmutableString kImageAtomicExchangeName("imageAtomicExchange");
29 constexpr const ImmutableString kAtomicCounterName("atomicCounter");
30
31 static const char kFunctionMangledNameSeparator = '(';
32
33 } // anonymous namespace
34
TSymbol(TSymbolTable * symbolTable,const ImmutableString & name,SymbolType symbolType,SymbolClass symbolClass,TExtension extension)35 TSymbol::TSymbol(TSymbolTable *symbolTable,
36 const ImmutableString &name,
37 SymbolType symbolType,
38 SymbolClass symbolClass,
39 TExtension extension)
40 : mName(name),
41 mUniqueId(symbolTable->nextUniqueId()),
42 mExtensions(
43 std::array<TExtension, 3u>{{extension, TExtension::UNDEFINED, TExtension::UNDEFINED}}),
44 mSymbolType(symbolType),
45 mSymbolClass(symbolClass)
46 {
47 ASSERT(mSymbolType == SymbolType::BuiltIn || extension == TExtension::UNDEFINED);
48 ASSERT(mName != "" || mSymbolType == SymbolType::AngleInternal ||
49 mSymbolType == SymbolType::Empty);
50 }
51
TSymbol(TSymbolTable * symbolTable,const ImmutableString & name,SymbolType symbolType,SymbolClass symbolClass,const std::array<TExtension,3u> & extensions)52 TSymbol::TSymbol(TSymbolTable *symbolTable,
53 const ImmutableString &name,
54 SymbolType symbolType,
55 SymbolClass symbolClass,
56 const std::array<TExtension, 3u> &extensions)
57 : mName(name),
58 mUniqueId(symbolTable->nextUniqueId()),
59 mExtensions(extensions),
60 mSymbolType(symbolType),
61 mSymbolClass(symbolClass)
62 {
63 ASSERT(mSymbolType == SymbolType::BuiltIn || extensions[0] == TExtension::UNDEFINED);
64 ASSERT(mName != "" || mSymbolType == SymbolType::AngleInternal ||
65 mSymbolType == SymbolType::Empty);
66 }
67
name() const68 ImmutableString TSymbol::name() const
69 {
70 if (!mName.empty())
71 {
72 return mName;
73 }
74 // This can be called for nameless function parameters in HLSL.
75 ASSERT(mSymbolType == SymbolType::AngleInternal ||
76 (mSymbolType == SymbolType::Empty && isVariable()));
77 int uniqueId = mUniqueId.get();
78 ImmutableStringBuilder symbolNameOut(sizeof(uniqueId) * 2u + 1u);
79 symbolNameOut << 's';
80 symbolNameOut.appendHex(mUniqueId.get());
81 return symbolNameOut;
82 }
83
getMangledName() const84 ImmutableString TSymbol::getMangledName() const
85 {
86 if (mSymbolClass == SymbolClass::Function)
87 {
88 // We do this instead of using proper virtual functions so that we can better support
89 // constexpr symbols.
90 return static_cast<const TFunction *>(this)->getFunctionMangledName();
91 }
92 ASSERT(mSymbolType != SymbolType::Empty);
93 return name();
94 }
95
TVariable(TSymbolTable * symbolTable,const ImmutableString & name,const TType * type,SymbolType symbolType,TExtension extension)96 TVariable::TVariable(TSymbolTable *symbolTable,
97 const ImmutableString &name,
98 const TType *type,
99 SymbolType symbolType,
100 TExtension extension)
101 : TSymbol(symbolTable, name, symbolType, SymbolClass::Variable, extension),
102 mType(type),
103 unionArray(nullptr)
104 {
105 ASSERT(mType);
106 ASSERT(name.empty() || symbolType != SymbolType::Empty);
107 }
108
TVariable(TSymbolTable * symbolTable,const ImmutableString & name,const TType * type,SymbolType symbolType,const std::array<TExtension,3u> & extensions)109 TVariable::TVariable(TSymbolTable *symbolTable,
110 const ImmutableString &name,
111 const TType *type,
112 SymbolType symbolType,
113 const std::array<TExtension, 3u> &extensions)
114 : TSymbol(symbolTable, name, symbolType, SymbolClass::Variable, extensions),
115 mType(type),
116 unionArray(nullptr)
117 {
118 ASSERT(mType);
119 ASSERT(name.empty() || symbolType != SymbolType::Empty);
120 }
121
TStructure(TSymbolTable * symbolTable,const ImmutableString & name,const TFieldList * fields,SymbolType symbolType)122 TStructure::TStructure(TSymbolTable *symbolTable,
123 const ImmutableString &name,
124 const TFieldList *fields,
125 SymbolType symbolType)
126 : TSymbol(symbolTable, name, symbolType, SymbolClass::Struct), TFieldListCollection(fields)
127 {}
128
createSamplerSymbols(const char * namePrefix,const TString & apiNamePrefix,TVector<const TVariable * > * outputSymbols,TMap<const TVariable *,TString> * outputSymbolsToAPINames,TSymbolTable * symbolTable) const129 void TStructure::createSamplerSymbols(const char *namePrefix,
130 const TString &apiNamePrefix,
131 TVector<const TVariable *> *outputSymbols,
132 TMap<const TVariable *, TString> *outputSymbolsToAPINames,
133 TSymbolTable *symbolTable) const
134 {
135 ASSERT(containsSamplers());
136 for (const auto *field : *mFields)
137 {
138 const TType *fieldType = field->type();
139 if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
140 {
141 std::stringstream fieldName = sh::InitializeStream<std::stringstream>();
142 fieldName << namePrefix << "_" << field->name();
143 TString fieldApiName = apiNamePrefix + ".";
144 fieldApiName += field->name().data();
145 fieldType->createSamplerSymbols(ImmutableString(fieldName.str()), fieldApiName,
146 outputSymbols, outputSymbolsToAPINames, symbolTable);
147 }
148 }
149 }
150
setName(const ImmutableString & name)151 void TStructure::setName(const ImmutableString &name)
152 {
153 ImmutableString *mutableName = const_cast<ImmutableString *>(&mName);
154 *mutableName = name;
155 }
156
TInterfaceBlock(TSymbolTable * symbolTable,const ImmutableString & name,const TFieldList * fields,const TLayoutQualifier & layoutQualifier,SymbolType symbolType,TExtension extension)157 TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable,
158 const ImmutableString &name,
159 const TFieldList *fields,
160 const TLayoutQualifier &layoutQualifier,
161 SymbolType symbolType,
162 TExtension extension)
163 : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extension),
164 TFieldListCollection(fields),
165 mBlockStorage(layoutQualifier.blockStorage),
166 mBinding(layoutQualifier.binding)
167 {
168 ASSERT(name != nullptr);
169 }
170
TInterfaceBlock(TSymbolTable * symbolTable,const ImmutableString & name,const TFieldList * fields,const TLayoutQualifier & layoutQualifier,SymbolType symbolType,const std::array<TExtension,3u> & extensions)171 TInterfaceBlock::TInterfaceBlock(TSymbolTable *symbolTable,
172 const ImmutableString &name,
173 const TFieldList *fields,
174 const TLayoutQualifier &layoutQualifier,
175 SymbolType symbolType,
176 const std::array<TExtension, 3u> &extensions)
177 : TSymbol(symbolTable, name, symbolType, SymbolClass::InterfaceBlock, extensions),
178 TFieldListCollection(fields),
179 mBlockStorage(layoutQualifier.blockStorage),
180 mBinding(layoutQualifier.binding)
181 {
182 ASSERT(name != nullptr);
183 }
184
TFunction(TSymbolTable * symbolTable,const ImmutableString & name,SymbolType symbolType,const TType * retType,bool knownToNotHaveSideEffects)185 TFunction::TFunction(TSymbolTable *symbolTable,
186 const ImmutableString &name,
187 SymbolType symbolType,
188 const TType *retType,
189 bool knownToNotHaveSideEffects)
190 : TSymbol(symbolTable, name, symbolType, SymbolClass::Function, TExtension::UNDEFINED),
191 mParametersVector(new TParamVector()),
192 mParameters(nullptr),
193 returnType(retType),
194 mMangledName(""),
195 mParamCount(0u),
196 mOp(EOpNull),
197 defined(false),
198 mHasPrototypeDeclaration(false),
199 mKnownToNotHaveSideEffects(knownToNotHaveSideEffects)
200 {
201 // Functions with an empty name are not allowed.
202 ASSERT(symbolType != SymbolType::Empty);
203 ASSERT(name != nullptr || symbolType == SymbolType::AngleInternal);
204 }
205
addParameter(const TVariable * p)206 void TFunction::addParameter(const TVariable *p)
207 {
208 ASSERT(mParametersVector);
209 mParametersVector->push_back(p);
210 mParameters = mParametersVector->data();
211 mParamCount = mParametersVector->size();
212 mMangledName = kEmptyImmutableString;
213 }
214
shareParameters(const TFunction & parametersSource)215 void TFunction::shareParameters(const TFunction ¶metersSource)
216 {
217 mParametersVector = nullptr;
218 mParameters = parametersSource.mParameters;
219 mParamCount = parametersSource.mParamCount;
220 ASSERT(parametersSource.name() == name());
221 mMangledName = parametersSource.mMangledName;
222 }
223
buildMangledName() const224 ImmutableString TFunction::buildMangledName() const
225 {
226 ImmutableString name = this->name();
227 std::string newName(name.data(), name.length());
228 newName += kFunctionMangledNameSeparator;
229
230 for (size_t i = 0u; i < mParamCount; ++i)
231 {
232 newName += mParameters[i]->getType().getMangledName();
233 }
234 return ImmutableString(newName);
235 }
236
isMain() const237 bool TFunction::isMain() const
238 {
239 return symbolType() == SymbolType::UserDefined && name() == kMainName;
240 }
241
isImageFunction() const242 bool TFunction::isImageFunction() const
243 {
244 return symbolType() == SymbolType::BuiltIn &&
245 (name() == kImageSizeName || name() == kImageLoadName || name() == kImageStoreName ||
246 name() == kImageAtomicExchangeName);
247 }
248
isAtomicCounterFunction() const249 bool TFunction::isAtomicCounterFunction() const
250 {
251 return SymbolType() == SymbolType::BuiltIn && name().beginsWith(kAtomicCounterName);
252 }
253 } // namespace sh
254